{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "name": "Untitled",
      "version": "0.3.2",
      "provenance": [],
      "toc_visible": true
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "RHvrwCqUFE73",
        "colab_type": "text"
      },
      "source": [
        "<!--COURSE_INFORMATION-->\n",
        "<img align=\"left\" style=\"padding-right:10px;\" src=\"https://sitejerk.com/images/google-earth-logo-png-5.png\" width=5% >\n",
        "<img align=\"right\" style=\"padding-left:10px;\" src=\"https://colab.research.google.com/img/colab_favicon_256px.png\" width=6% >\n",
        "\n",
        "\n",
        ">> *This notebook is part of the free course [EEwPython](https://colab.research.google.com/github/csaybar/EEwPython/blob/master/index.ipynb); the content is available [on GitHub](https://github.com/csaybar/EEwPython)* and released under the [Apache 2.0 License](https://www.gnu.org/licenses/gpl-3.0.en.html). 99% of this material has been adapted from [Google Earth Engine Guides](https://developers.google.com/earth-engine/)."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "NGoK_HdhFNT3",
        "colab_type": "text"
      },
      "source": [
        "<!--NAVIGATION-->\n",
        " < [Geometry, Feature and FeatureCollection](4_features.ipynb) | [Contents](index.ipynb) |  [Joins](6_Joins.ipynb)>\n",
        "\n",
        "<a href=\"https://colab.research.google.com/github/csaybar/EEwPython/blob/master/5_Reducer.ipynb\"><img align=\"left\" src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open in Colab\" title=\"Open and Execute in Google Colaboratory\"></a>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "LPIQRFp2FljW",
        "colab_type": "text"
      },
      "source": [
        "<center>\n",
        "<h1>Google Earth Engine with Python </h1>\n",
        "<h2> Reducers </h2>\n",
        "</center>\n",
        "<h2> Topics:</h2>\n",
        "\n",
        "1. Reducer Overview\n",
        "2. ImageCollection Reductions\n",
        "3. Image Reductions\n",
        "4. Statistics of an Image Region\n",
        "5. Statistics of Image Regions\n",
        "6. Statistics of Image Neighborhoods\n",
        "7. Raster to Vector Conversion\n",
        "8. Vector to Raster Conversion\n",
        "9. Grouped Reductions and Zonal Statistics\n",
        "10. Weighted Reductions\n",
        "11. Linear Regression\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "vJGY1BQ2Ftmi",
        "colab_type": "text"
      },
      "source": [
        "## Connecting GEE with Google Services"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "aN8M959CfDTs",
        "colab_type": "text"
      },
      "source": [
        "- **Authenticate to Earth Engine**"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "8oYo6SvGFo-A",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "!pip install earthengine-api #earth-engine Python API"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "8n2S745ufFBt",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "!earthengine authenticate "
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "vtl_FhUfFvjl",
        "colab_type": "text"
      },
      "source": [
        "- **Authenticate to Google Drive (OPTIONAL)**"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "cZCBrVDeFyHn",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "from google.colab import drive\n",
        "drive.mount('/content/drive')"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "ReJ-wwaJfJ1Z",
        "colab_type": "text"
      },
      "source": [
        "- **Authenticate to Google Cloud (OPTIONAL)**"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "uoQ4pNffF0IA",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "from google.colab import auth\n",
        "auth.authenticate_user()"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "-mmYC9HefYEh",
        "colab_type": "text"
      },
      "source": [
        "## Testing the software setup"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "iN5Rlm4ifc-C",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "# Earth Engine Python API\n",
        "import ee\n",
        "ee.Initialize()"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "trpdw1TBffmi",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "import folium\n",
        "\n",
        "# Define the URL format used for Earth Engine generated map tiles.\n",
        "EE_TILES = 'https://earthengine.googleapis.com/map/{mapid}/{{z}}/{{x}}/{{y}}?token={token}'\n",
        "\n",
        "print('Folium version: ' + folium.__version__)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "WdSGJyzBf0OS",
        "colab_type": "code",
        "cellView": "form",
        "colab": {}
      },
      "source": [
        "#@title Mapdisplay: Display GEE objects using folium.\n",
        "def Mapdisplay(center, dicc, Tiles=\"OpensTreetMap\",zoom_start=10):\n",
        "    '''\n",
        "    :param center: Center of the map (Latitude and Longitude).\n",
        "    :param dicc: Earth Engine Geometries or Tiles dictionary\n",
        "    :param Tiles: Mapbox Bright,Mapbox Control Room,Stamen Terrain,Stamen Toner,stamenwatercolor,cartodbpositron.\n",
        "    :zoom_start: Initial zoom level for the map.\n",
        "    :return: A folium.Map object.\n",
        "    '''\n",
        "    mapViz = folium.Map(location=center,tiles=Tiles, zoom_start=zoom_start)\n",
        "    for k,v in dicc.items():\n",
        "      if ee.image.Image in [type(x) for x in v.values()]:\n",
        "        folium.TileLayer(\n",
        "            tiles = EE_TILES.format(**v),\n",
        "            attr  = 'Google Earth Engine',\n",
        "            overlay =True,\n",
        "            name  = k\n",
        "          ).add_to(mapViz)\n",
        "      else:\n",
        "        folium.GeoJson(\n",
        "        data = v,\n",
        "        name = k\n",
        "          ).add_to(mapViz)\n",
        "    mapViz.add_child(folium.LayerControl())\n",
        "    return mapViz"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "V7ItGnKsFOZg",
        "colab_type": "text"
      },
      "source": [
        "# 1. Reducer Overview\n",
        "\n",
        "Reducers are the way to aggregate data over time, space, bands, arrays and other data structures in Earth Engine. The `ee.Reducer` class specifies how data is aggregated. The reducers in this class can specify a simple statistic to use for the aggregation (e.g. minimum, maximum, mean, median, standard deviation, etc.), or a more complex summary of the input data (e.g. histogram, linear regression, list). Reductions may occur over:\n",
        "\n",
        "- **time**  = `imageCollection.reduce()`\n",
        "- **space** = `image.reduceRegion()` and `image.reduceNeighborhood()`**\n",
        "- **bands**  = `image.reduce()`,\n",
        "\n",
        "Or the attribute space of a `FeatureCollection` (`featureCollection.reduceColumns()` or `FeatureCollection` methods that start with `aggregate_`).\n",
        "\n",
        "\n",
        "## Reducers have inputs and outputs\n",
        "\n",
        "Reducers take an input dataset and produce a single output. When a single input reducer is applied to a multi-band image, Earth Engine automatically replicates the reducer and applies it separately to each band. As a result, the output image has the same number of bands as the input image; each band in the output is the reduction of pixels from the corresponding band in the input data. Some reducers take tuples of input datasets. These reducers will not be automatically replicated for each band. For example, `ee.Reducer.LinearRegression()` takes multiple predictor datasets (representing independent variables in the regression) in a particular order (see Regression reducers section bellow).\n",
        "\n",
        "Some reducers produce multiple outputs, for example `ee.Reducer.minMax()`, `ee.Reducer.histogram()` or `ee.Reducer.toList()`. For example:"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "e9ejEh7qEke0",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "# Load and filter the Sentinel-2 image collection.\n",
        "collection = ee.ImageCollection('COPERNICUS/S2')\\\n",
        "               .filterDate('2016-01-01', '2016-12-31')\\\n",
        "               .filterBounds(ee.Geometry.Point([-81.31, 29.90]))\n",
        "\n",
        "# Reduce the collection.\n",
        "extrema = collection.reduce(ee.Reducer.minMax())"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "uqPsM4E4Jlxm",
        "colab_type": "text"
      },
      "source": [
        "This will produce an output with twice the number of bands of the inputs, where band names in the output have ‘_min’ or ‘_max’ appended to the band name.\n",
        "\n",
        "The output type should match the computation. For example, a reducer applied to an ImageCollection has an Image output. Because the output is interpreted as a pixel value, you must use reducers with a numeric output to reduce an ImageCollection (reducers like `toList()` or `histogram()` won’t work).\n",
        "\n",
        "## Reducers use weighted inputs\n",
        "\n",
        "By default, reductions over pixel values are weighted by their mask, though this behavior can be changed (see the Weighting section bellow). Pixels with mask equal to 0 will not be used in the reduction.\n",
        "\n",
        "## Combining reducers\n",
        "\n",
        "If your intent is to apply multiple reducers to the same inputs, it's good practice to `combine()` the reducers for efficiency. Specifically, calling `combine()` on a reducer with `sharedInputs` set to `true` will result in only a single pass over the data. For example, to compute the mean and standard deviation of pixels in an image, you could use something like this:"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "T8JKG8UbJvXu",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "from pprint import pprint \n",
        "\n",
        "# Load a Landsat 8 image.\n",
        "image = ee.Image('LANDSAT/LC08/C01/T1/LC08_044034_20140318')\n",
        "\n",
        "# Combine the mean and standard deviation reducers.\n",
        "reducers = ee.Reducer.mean().combine(\n",
        "  reducer2=ee.Reducer.stdDev(),\n",
        "  sharedInputs=True\n",
        ")\n",
        "\n",
        "# Use the combined reducer to get the mean and SD of the image.\n",
        "stats = image.reduceRegion(\n",
        "  reducer=reducers,\n",
        "  bestEffort=True,\n",
        ")\n",
        "\n",
        "# Display the dictionary of band means and SDs.\n",
        "pprint(stats.getInfo())"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "BzB0gON0Mgsj",
        "colab_type": "text"
      },
      "source": [
        "In the output, note that the names of the reducers have been appended to the names of the inputs to distinguish the reducer outputs. This behavior also applies to image outputs, which will have the name of the reducer appended to output band names."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "sLgQV4zmMoXM",
        "colab_type": "text"
      },
      "source": [
        "# 2. ImageCollection Reductions\n",
        "\n",
        "Consider the example of needing to take the median over a time series of images represented by an `ImageCollection`. To reduce an `ImageCollection`, use `imageCollection.reduce()`. This reduces the collection of images to an individual image as illustrated in Figure 1. Specifically, the output is computed pixel-wise, such that each pixel in the output is composed of the median value of all the images in the collection at that location. To get other statistics, such as mean, sum, variance, an arbitrary percentile, etc., the appropriate reducer should be selected and applied. For basic statistics like min, max, mean, etc., `ImageCollection` has shortcut methods like `min()`, `max()`, `mean()`, etc. They function in exactly the same way as calling reduce(), except the resultant band names will not have the name of the reducer appended.\n",
        "\n",
        "\n",
        "<center>\n",
        "<image src = \"https://developers.google.com/earth-engine/images/Reduce_ImageCollection.png\">  \n",
        "</center>\n",
        "\n",
        "<center>\n",
        "  Figure 1. Illustration of an ee.Reducer applied to an ImageCollection."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "uT1SchrQNMOM",
        "colab_type": "code",
        "outputId": "f773040c-babf-4d7e-9919-0c62e1bf9cb3",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 559
        }
      },
      "source": [
        "# Load an image collection, filtered so it's not too much data.\n",
        "collection = ee.ImageCollection('LANDSAT/LT05/C01/T1')\\\n",
        "               .filterDate('2008-01-01', '2008-12-31')\\\n",
        "               .filter(ee.Filter.eq('WRS_PATH', 44))\\\n",
        "               .filter(ee.Filter.eq('WRS_ROW', 34))\n",
        "\n",
        "# Compute the median in each band, each pixel.\n",
        "# Band names are B1_median, B2_median, etc.\n",
        "median = collection.reduce(ee.Reducer.median())\n",
        "\n",
        "# The output is an Image.  Add it to the map.\n",
        "vis_param = {'bands': ['B4_median', 'B3_median', 'B2_median'], 'gamma': 1.6}\n",
        "median_tk = median.getMapId(vis_param)\n",
        "\n",
        "center = [37.7924, -122.3355]\n",
        "Mapdisplay(center,{'Landsat 5':median_tk},zoom_start=9)"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/html": [
              "<div style=\"width:100%;\"><div style=\"position:relative;width:100%;height:0;padding-bottom:60%;\"><iframe src=\"data:text/html;charset=utf-8;base64,PCFET0NUWVBFIGh0bWw+CjxoZWFkPiAgICAKICAgIDxtZXRhIGh0dHAtZXF1aXY9ImNvbnRlbnQtdHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PVVURi04IiAvPgogICAgPHNjcmlwdD5MX1BSRUZFUl9DQU5WQVM9ZmFsc2U7IExfTk9fVE9VQ0g9ZmFsc2U7IExfRElTQUJMRV8zRD1mYWxzZTs8L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS40LjAvZGlzdC9sZWFmbGV0LmpzIj48L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2NvZGUuanF1ZXJ5LmNvbS9qcXVlcnktMS4xMi40Lm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvanMvYm9vdHN0cmFwLm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9jZG5qcy5jbG91ZGZsYXJlLmNvbS9hamF4L2xpYnMvTGVhZmxldC5hd2Vzb21lLW1hcmtlcnMvMi4wLjIvbGVhZmxldC5hd2Vzb21lLW1hcmtlcnMuanMiPjwvc2NyaXB0PgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS40LjAvZGlzdC9sZWFmbGV0LmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9jc3MvYm9vdHN0cmFwLm1pbi5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvY3NzL2Jvb3RzdHJhcC10aGVtZS5taW4uY3NzIi8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vbWF4Y2RuLmJvb3RzdHJhcGNkbi5jb20vZm9udC1hd2Vzb21lLzQuNi4zL2Nzcy9mb250LWF3ZXNvbWUubWluLmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2NkbmpzLmNsb3VkZmxhcmUuY29tL2FqYXgvbGlicy9MZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy8yLjAuMi9sZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9yYXdjZG4uZ2l0aGFjay5jb20vcHl0aG9uLXZpc3VhbGl6YXRpb24vZm9saXVtL21hc3Rlci9mb2xpdW0vdGVtcGxhdGVzL2xlYWZsZXQuYXdlc29tZS5yb3RhdGUuY3NzIi8+CiAgICA8c3R5bGU+aHRtbCwgYm9keSB7d2lkdGg6IDEwMCU7aGVpZ2h0OiAxMDAlO21hcmdpbjogMDtwYWRkaW5nOiAwO308L3N0eWxlPgogICAgPHN0eWxlPiNtYXAge3Bvc2l0aW9uOmFic29sdXRlO3RvcDowO2JvdHRvbTowO3JpZ2h0OjA7bGVmdDowO308L3N0eWxlPgogICAgCiAgICA8bWV0YSBuYW1lPSJ2aWV3cG9ydCIgY29udGVudD0id2lkdGg9ZGV2aWNlLXdpZHRoLAogICAgICAgIGluaXRpYWwtc2NhbGU9MS4wLCBtYXhpbXVtLXNjYWxlPTEuMCwgdXNlci1zY2FsYWJsZT1ubyIgLz4KICAgIDxzdHlsZT4jbWFwXzFiNWQxNDE5OTk5NzQ1NzA4NzJlNjEwMTNiMTAyMTBhIHsKICAgICAgICBwb3NpdGlvbjogcmVsYXRpdmU7CiAgICAgICAgd2lkdGg6IDEwMC4wJTsKICAgICAgICBoZWlnaHQ6IDEwMC4wJTsKICAgICAgICBsZWZ0OiAwLjAlOwogICAgICAgIHRvcDogMC4wJTsKICAgICAgICB9CiAgICA8L3N0eWxlPgo8L2hlYWQ+Cjxib2R5PiAgICAKICAgIAogICAgPGRpdiBjbGFzcz0iZm9saXVtLW1hcCIgaWQ9Im1hcF8xYjVkMTQxOTk5OTc0NTcwODcyZTYxMDEzYjEwMjEwYSIgPjwvZGl2Pgo8L2JvZHk+CjxzY3JpcHQ+ICAgIAogICAgCiAgICAKICAgICAgICB2YXIgYm91bmRzID0gbnVsbDsKICAgIAoKICAgIHZhciBtYXBfMWI1ZDE0MTk5OTk3NDU3MDg3MmU2MTAxM2IxMDIxMGEgPSBMLm1hcCgKICAgICAgICAnbWFwXzFiNWQxNDE5OTk5NzQ1NzA4NzJlNjEwMTNiMTAyMTBhJywgewogICAgICAgIGNlbnRlcjogWzM3Ljc5MjQsIC0xMjIuMzM1NV0sCiAgICAgICAgem9vbTogOSwKICAgICAgICBtYXhCb3VuZHM6IGJvdW5kcywKICAgICAgICBsYXllcnM6IFtdLAogICAgICAgIHdvcmxkQ29weUp1bXA6IGZhbHNlLAogICAgICAgIGNyczogTC5DUlMuRVBTRzM4NTcsCiAgICAgICAgem9vbUNvbnRyb2w6IHRydWUsCiAgICAgICAgfSk7CgoKICAgIAogICAgdmFyIHRpbGVfbGF5ZXJfOTlmZDZiZGM1MzdlNDBmZWI3YTFmYzQ1MmIyMWQ2YzUgPSBMLnRpbGVMYXllcigKICAgICAgICAnaHR0cHM6Ly97c30udGlsZS5vcGVuc3RyZWV0bWFwLm9yZy97en0ve3h9L3t5fS5wbmcnLAogICAgICAgIHsKICAgICAgICAiYXR0cmlidXRpb24iOiBudWxsLAogICAgICAgICJkZXRlY3RSZXRpbmEiOiBmYWxzZSwKICAgICAgICAibWF4TmF0aXZlWm9vbSI6IDE4LAogICAgICAgICJtYXhab29tIjogMTgsCiAgICAgICAgIm1pblpvb20iOiAwLAogICAgICAgICJub1dyYXAiOiBmYWxzZSwKICAgICAgICAib3BhY2l0eSI6IDEsCiAgICAgICAgInN1YmRvbWFpbnMiOiAiYWJjIiwKICAgICAgICAidG1zIjogZmFsc2UKfSkuYWRkVG8obWFwXzFiNWQxNDE5OTk5NzQ1NzA4NzJlNjEwMTNiMTAyMTBhKTsKICAgIHZhciB0aWxlX2xheWVyX2NmZjgzMjM3ZjdhZTQ3ZjE5OWVlOGYwNGIyZTBhZjY5ID0gTC50aWxlTGF5ZXIoCiAgICAgICAgJ2h0dHBzOi8vZWFydGhlbmdpbmUuZ29vZ2xlYXBpcy5jb20vbWFwLzVhOTlhNjExNGU1NGEzYzQ3MDdiNjk1YzQyYTQxNDQ3L3t6fS97eH0ve3l9P3Rva2VuPWFkOWY2ZDI3NGVkMjQyZDc5ZmU4YjY1YWRlMmUxOGEwJywKICAgICAgICB7CiAgICAgICAgImF0dHJpYnV0aW9uIjogIkdvb2dsZSBFYXJ0aCBFbmdpbmUiLAogICAgICAgICJkZXRlY3RSZXRpbmEiOiBmYWxzZSwKICAgICAgICAibWF4TmF0aXZlWm9vbSI6IDE4LAogICAgICAgICJtYXhab29tIjogMTgsCiAgICAgICAgIm1pblpvb20iOiAwLAogICAgICAgICJub1dyYXAiOiBmYWxzZSwKICAgICAgICAib3BhY2l0eSI6IDEsCiAgICAgICAgInN1YmRvbWFpbnMiOiAiYWJjIiwKICAgICAgICAidG1zIjogZmFsc2UKfSkuYWRkVG8obWFwXzFiNWQxNDE5OTk5NzQ1NzA4NzJlNjEwMTNiMTAyMTBhKTsKICAgIAogICAgICAgICAgICB2YXIgbGF5ZXJfY29udHJvbF9jYzdlZjZkZmYzN2U0YjA5YTBmODM0ZTEzZDk4ZTVmMSA9IHsKICAgICAgICAgICAgICAgIGJhc2VfbGF5ZXJzIDogeyAib3BlbnN0cmVldG1hcCIgOiB0aWxlX2xheWVyXzk5ZmQ2YmRjNTM3ZTQwZmViN2ExZmM0NTJiMjFkNmM1LCB9LAogICAgICAgICAgICAgICAgb3ZlcmxheXMgOiB7ICJMYW5kc2F0IDUiIDogdGlsZV9sYXllcl9jZmY4MzIzN2Y3YWU0N2YxOTllZThmMDRiMmUwYWY2OSwgfQogICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgTC5jb250cm9sLmxheWVycygKICAgICAgICAgICAgICAgIGxheWVyX2NvbnRyb2xfY2M3ZWY2ZGZmMzdlNGIwOWEwZjgzNGUxM2Q5OGU1ZjEuYmFzZV9sYXllcnMsCiAgICAgICAgICAgICAgICBsYXllcl9jb250cm9sX2NjN2VmNmRmZjM3ZTRiMDlhMGY4MzRlMTNkOThlNWYxLm92ZXJsYXlzLAogICAgICAgICAgICAgICAge3Bvc2l0aW9uOiAndG9wcmlnaHQnLAogICAgICAgICAgICAgICAgIGNvbGxhcHNlZDogdHJ1ZSwKICAgICAgICAgICAgICAgICBhdXRvWkluZGV4OiB0cnVlCiAgICAgICAgICAgICAgICB9KS5hZGRUbyhtYXBfMWI1ZDE0MTk5OTk3NDU3MDg3MmU2MTAxM2IxMDIxMGEpOwogICAgICAgICAgICAKICAgICAgICAKPC9zY3JpcHQ+\" style=\"position:absolute;width:100%;height:100%;left:0;top:0;border:none !important;\" allowfullscreen webkitallowfullscreen mozallowfullscreen></iframe></div></div>"
            ],
            "text/plain": [
              "<folium.folium.Map at 0x7fd39948b940>"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 35
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "hFG8e10dOkWu",
        "colab_type": "text"
      },
      "source": [
        "This returns a multi-band Image, each pixel of which is the median of all unmasked pixels in the ImageCollection at that pixel location. Specifically, the reducer has been repeated for each band of the input imagery. Note that the band names have the name of the reducer appended: ‘B1_median’, ‘B2_median’, etc.\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "_GNMkQhbjtW1",
        "colab_type": "text"
      },
      "source": [
        "# 2. Image Reductions\n",
        "\n",
        "To reduce an `Image`, use `image.reduce()`. Reducing an image functions in an analogous way to `imageCollection.reduce()`, except the bands of the image are input to the reducer rather than the images in the collection. The output is also an image with number of bands equal to number of reducer outputs. For example:\n",
        "\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "E71SF93vjz8X",
        "colab_type": "code",
        "outputId": "63b50976-e6fd-4b70-adcf-ca57a4149250",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 559
        }
      },
      "source": [
        "# Load an image and select some bands of interest.\n",
        "image = ee.Image('LANDSAT/LC08/C01/T1/LC08_044034_20140318')\\\n",
        "          .select(['B4', 'B3', 'B2'])\n",
        "\n",
        "# Reduce the image to get a one-band maximum value image.\n",
        "maxValue = image.reduce(ee.Reducer.max())\n",
        "\n",
        "# Display the result\n",
        "vis_param = {'max': 13000, 'gamma': 1.6}\n",
        "center = [37.7924, -122.3355]\n",
        "\n",
        "maxValue_tk = maxValue.getMapId(vis_param)\n",
        "Mapdisplay(center,{'Landsat 5':maxValue_tk},zoom_start=10)"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/html": [
              "<div style=\"width:100%;\"><div style=\"position:relative;width:100%;height:0;padding-bottom:60%;\"><iframe src=\"data:text/html;charset=utf-8;base64,PCFET0NUWVBFIGh0bWw+CjxoZWFkPiAgICAKICAgIDxtZXRhIGh0dHAtZXF1aXY9ImNvbnRlbnQtdHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PVVURi04IiAvPgogICAgPHNjcmlwdD5MX1BSRUZFUl9DQU5WQVM9ZmFsc2U7IExfTk9fVE9VQ0g9ZmFsc2U7IExfRElTQUJMRV8zRD1mYWxzZTs8L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS40LjAvZGlzdC9sZWFmbGV0LmpzIj48L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2NvZGUuanF1ZXJ5LmNvbS9qcXVlcnktMS4xMi40Lm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvanMvYm9vdHN0cmFwLm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9jZG5qcy5jbG91ZGZsYXJlLmNvbS9hamF4L2xpYnMvTGVhZmxldC5hd2Vzb21lLW1hcmtlcnMvMi4wLjIvbGVhZmxldC5hd2Vzb21lLW1hcmtlcnMuanMiPjwvc2NyaXB0PgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS40LjAvZGlzdC9sZWFmbGV0LmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9jc3MvYm9vdHN0cmFwLm1pbi5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvY3NzL2Jvb3RzdHJhcC10aGVtZS5taW4uY3NzIi8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vbWF4Y2RuLmJvb3RzdHJhcGNkbi5jb20vZm9udC1hd2Vzb21lLzQuNi4zL2Nzcy9mb250LWF3ZXNvbWUubWluLmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2NkbmpzLmNsb3VkZmxhcmUuY29tL2FqYXgvbGlicy9MZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy8yLjAuMi9sZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9yYXdjZG4uZ2l0aGFjay5jb20vcHl0aG9uLXZpc3VhbGl6YXRpb24vZm9saXVtL21hc3Rlci9mb2xpdW0vdGVtcGxhdGVzL2xlYWZsZXQuYXdlc29tZS5yb3RhdGUuY3NzIi8+CiAgICA8c3R5bGU+aHRtbCwgYm9keSB7d2lkdGg6IDEwMCU7aGVpZ2h0OiAxMDAlO21hcmdpbjogMDtwYWRkaW5nOiAwO308L3N0eWxlPgogICAgPHN0eWxlPiNtYXAge3Bvc2l0aW9uOmFic29sdXRlO3RvcDowO2JvdHRvbTowO3JpZ2h0OjA7bGVmdDowO308L3N0eWxlPgogICAgCiAgICA8bWV0YSBuYW1lPSJ2aWV3cG9ydCIgY29udGVudD0id2lkdGg9ZGV2aWNlLXdpZHRoLAogICAgICAgIGluaXRpYWwtc2NhbGU9MS4wLCBtYXhpbXVtLXNjYWxlPTEuMCwgdXNlci1zY2FsYWJsZT1ubyIgLz4KICAgIDxzdHlsZT4jbWFwX2NhYTY5NjQ4NzFiNjQwNWViNmNjNzk2ZWQ2MDJhYTFjIHsKICAgICAgICBwb3NpdGlvbjogcmVsYXRpdmU7CiAgICAgICAgd2lkdGg6IDEwMC4wJTsKICAgICAgICBoZWlnaHQ6IDEwMC4wJTsKICAgICAgICBsZWZ0OiAwLjAlOwogICAgICAgIHRvcDogMC4wJTsKICAgICAgICB9CiAgICA8L3N0eWxlPgo8L2hlYWQ+Cjxib2R5PiAgICAKICAgIAogICAgPGRpdiBjbGFzcz0iZm9saXVtLW1hcCIgaWQ9Im1hcF9jYWE2OTY0ODcxYjY0MDVlYjZjYzc5NmVkNjAyYWExYyIgPjwvZGl2Pgo8L2JvZHk+CjxzY3JpcHQ+ICAgIAogICAgCiAgICAKICAgICAgICB2YXIgYm91bmRzID0gbnVsbDsKICAgIAoKICAgIHZhciBtYXBfY2FhNjk2NDg3MWI2NDA1ZWI2Y2M3OTZlZDYwMmFhMWMgPSBMLm1hcCgKICAgICAgICAnbWFwX2NhYTY5NjQ4NzFiNjQwNWViNmNjNzk2ZWQ2MDJhYTFjJywgewogICAgICAgIGNlbnRlcjogWzM3Ljc5MjQsIC0xMjIuMzM1NV0sCiAgICAgICAgem9vbTogMTAsCiAgICAgICAgbWF4Qm91bmRzOiBib3VuZHMsCiAgICAgICAgbGF5ZXJzOiBbXSwKICAgICAgICB3b3JsZENvcHlKdW1wOiBmYWxzZSwKICAgICAgICBjcnM6IEwuQ1JTLkVQU0czODU3LAogICAgICAgIHpvb21Db250cm9sOiB0cnVlLAogICAgICAgIH0pOwoKCiAgICAKICAgIHZhciB0aWxlX2xheWVyXzMzNzI4NmE0MDU4YzRhYTZiYjdiOTZjZmM0OTg0ZmQ4ID0gTC50aWxlTGF5ZXIoCiAgICAgICAgJ2h0dHBzOi8ve3N9LnRpbGUub3BlbnN0cmVldG1hcC5vcmcve3p9L3t4fS97eX0ucG5nJywKICAgICAgICB7CiAgICAgICAgImF0dHJpYnV0aW9uIjogbnVsbCwKICAgICAgICAiZGV0ZWN0UmV0aW5hIjogZmFsc2UsCiAgICAgICAgIm1heE5hdGl2ZVpvb20iOiAxOCwKICAgICAgICAibWF4Wm9vbSI6IDE4LAogICAgICAgICJtaW5ab29tIjogMCwKICAgICAgICAibm9XcmFwIjogZmFsc2UsCiAgICAgICAgIm9wYWNpdHkiOiAxLAogICAgICAgICJzdWJkb21haW5zIjogImFiYyIsCiAgICAgICAgInRtcyI6IGZhbHNlCn0pLmFkZFRvKG1hcF9jYWE2OTY0ODcxYjY0MDVlYjZjYzc5NmVkNjAyYWExYyk7CiAgICB2YXIgdGlsZV9sYXllcl80NjI1NzgxYzdkODA0YmRlODZmZGI3NDk0Y2U1MzYxYyA9IEwudGlsZUxheWVyKAogICAgICAgICdodHRwczovL2VhcnRoZW5naW5lLmdvb2dsZWFwaXMuY29tL21hcC9lMDYyNDI1OTZhMTg2ODg4ZTgxN2U5YmZjYTc0YzFiNi97en0ve3h9L3t5fT90b2tlbj01OWI1ZTQ1OGNiZWI4ZGFjNzEwNjBmMjIzMjMzOGNhYicsCiAgICAgICAgewogICAgICAgICJhdHRyaWJ1dGlvbiI6ICJHb29nbGUgRWFydGggRW5naW5lIiwKICAgICAgICAiZGV0ZWN0UmV0aW5hIjogZmFsc2UsCiAgICAgICAgIm1heE5hdGl2ZVpvb20iOiAxOCwKICAgICAgICAibWF4Wm9vbSI6IDE4LAogICAgICAgICJtaW5ab29tIjogMCwKICAgICAgICAibm9XcmFwIjogZmFsc2UsCiAgICAgICAgIm9wYWNpdHkiOiAxLAogICAgICAgICJzdWJkb21haW5zIjogImFiYyIsCiAgICAgICAgInRtcyI6IGZhbHNlCn0pLmFkZFRvKG1hcF9jYWE2OTY0ODcxYjY0MDVlYjZjYzc5NmVkNjAyYWExYyk7CiAgICAKICAgICAgICAgICAgdmFyIGxheWVyX2NvbnRyb2xfNzhhOGFiNzJjNzMzNDM1NTliMGNjOGMyMjQ1MDg5MzIgPSB7CiAgICAgICAgICAgICAgICBiYXNlX2xheWVycyA6IHsgIm9wZW5zdHJlZXRtYXAiIDogdGlsZV9sYXllcl8zMzcyODZhNDA1OGM0YWE2YmI3Yjk2Y2ZjNDk4NGZkOCwgfSwKICAgICAgICAgICAgICAgIG92ZXJsYXlzIDogeyAiTGFuZHNhdCA1IiA6IHRpbGVfbGF5ZXJfNDYyNTc4MWM3ZDgwNGJkZTg2ZmRiNzQ5NGNlNTM2MWMsIH0KICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgIEwuY29udHJvbC5sYXllcnMoCiAgICAgICAgICAgICAgICBsYXllcl9jb250cm9sXzc4YThhYjcyYzczMzQzNTU5YjBjYzhjMjI0NTA4OTMyLmJhc2VfbGF5ZXJzLAogICAgICAgICAgICAgICAgbGF5ZXJfY29udHJvbF83OGE4YWI3MmM3MzM0MzU1OWIwY2M4YzIyNDUwODkzMi5vdmVybGF5cywKICAgICAgICAgICAgICAgIHtwb3NpdGlvbjogJ3RvcHJpZ2h0JywKICAgICAgICAgICAgICAgICBjb2xsYXBzZWQ6IHRydWUsCiAgICAgICAgICAgICAgICAgYXV0b1pJbmRleDogdHJ1ZQogICAgICAgICAgICAgICAgfSkuYWRkVG8obWFwX2NhYTY5NjQ4NzFiNjQwNWViNmNjNzk2ZWQ2MDJhYTFjKTsKICAgICAgICAgICAgCiAgICAgICAgCjwvc2NyaXB0Pg==\" style=\"position:absolute;width:100%;height:100%;left:0;top:0;border:none !important;\" allowfullscreen webkitallowfullscreen mozallowfullscreen></iframe></div></div>"
            ],
            "text/plain": [
              "<folium.folium.Map at 0x7fd3993c07f0>"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 50
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "fWaU-JSQuRDL",
        "colab_type": "text"
      },
      "source": [
        "# 4. Statistics of an Image Region\n",
        "\n",
        "Suppose there is need to calculate statistics over a region (or regions) of an `ee.Image`. To get statistics of pixel values in an image region, use `image.reduceRegion()`. This reduces all the pixels in the region(s) to a statistic or other compact representation of the pixel data in the region (e.g. histogram). The region is represented as a `Geometry`, which might be a polygon, containing many pixels, or it might be a single point, in which case there will only be one pixel in the region. In either case, as illustrated in Figure 2,  the output is a statistic derived from the pixels in the region.\n",
        "\n",
        "<center>\n",
        "<image src=\" https://developers.google.com/earth-engine/images/Reduce_region_diagram.png\" >\n",
        "</center>\n",
        "  \n",
        "\n",
        "<center>\n",
        "  Figure 2. An illustration of an `ee.Reducer` applied to an image and a region.\n",
        "</center>\n",
        "  \n",
        "  \n",
        "For an example of getting pixel statistics in a region of an image using reduceRegion(), consider finding the mean spectral values of a 5-year Landsat composite within the boundaries of the Sierra Nevada Coniferous Forest:\n",
        "  \n",
        "  "
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "L4-1dVMou92O",
        "colab_type": "code",
        "outputId": "f1adf0f9-feeb-4fc3-c6ef-17bbb1c140a6",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 143
        }
      },
      "source": [
        "# Load input imagery: Landsat 7 5-year composite.\n",
        "image = ee.Image('LANDSAT/LE7_TOA_5YEAR/2008_2012')\n",
        "\n",
        "# Load an input region: Sierra Nevada mixed conifer forest.\n",
        "region = ee.Feature(ee.FeatureCollection(\n",
        "  'ft:1Ec8IWsP8asxN-ywSqgXWMuBaxI6pPaeh6hC64lA')\n",
        "  .filter(ee.Filter.eq('G200_REGIO', 'Sierra Nevada Coniferous Forests'))\\\n",
        "  .first())\n",
        "\n",
        "# Reduce the region. The region parameter is the Feature geometry.\n",
        "meanDictionary = image.reduceRegion(**{\n",
        "  'reducer': ee.Reducer.mean(),\n",
        "  'geometry': region.geometry(),\n",
        "  'scale': 30,\n",
        "  'maxPixels': 1e9\n",
        "})\n",
        "\n",
        "# The result is a Dictionary.  Print it.\n",
        "pprint(meanDictionary.getInfo())"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "{'B1': 24.42471064449399,\n",
            " 'B2': 22.57720943212569,\n",
            " 'B3': 20.919795223268885,\n",
            " 'B4': 53.67924806897354,\n",
            " 'B5': 34.62817356591265,\n",
            " 'B6_VCID_2': 198.17174001586343,\n",
            " 'B7': 21.361143212564883}\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "KSqQ91Fqxatx",
        "colab_type": "text"
      },
      "source": [
        "Note that in this example the reduction is specified by providing the `reducer` (`ee.Reducer.mean()`), the `geometry` (`region.geometry()`), the `scale` (30 meters) and `maxPixels` for the maximum number of pixels to input to the reducer. A scale should always be specified in reduceRegion() calls. This is because in complex processing flows, which may involve data from different sources with different scales, the scale of the output will not be unambiguously determined from the inputs. In that case, the scale defaults to 1 degree, which generally produces unsatisfactory results. See [this page](https://developers.google.com/earth-engine/scale) for more information about how Earth Engine handles scale.\n",
        "\n",
        "There are two ways to set the scale: by specifying the scale parameter, or by specifying a CRS and CRS transform. (See the [glossary](https://developers.google.com/earth-engine/glossary) for more information about CRS's and CRS transforms). For example, the meanDictionary reduction (above) is equivalent to the following:"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "zmF-nUsCxBdp",
        "colab_type": "code",
        "outputId": "68b0300e-452a-4c90-87c4-0219b633e52c",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 143
        }
      },
      "source": [
        "# As an alternative to specifying scale, specify a CRS and a CRS transform.\n",
        "# Make this array by constructing a 4326 projection at 30 meters,\n",
        "# then copying the bounds of the composite, from composite.projection().\n",
        "affine = [0.00026949458523585647, 0, -180, 0, -0.00026949458523585647, 86.0000269494563];\n",
        "\n",
        "# Perform the reduction, print the result.\n",
        "pprint(image.reduceRegion(**{\n",
        "  'reducer': ee.Reducer.mean(),\n",
        "  'geometry': region.geometry(),\n",
        "  'crs': 'EPSG:4326',\n",
        "  'crsTransform': affine,\n",
        "  'maxPixels': 1e9\n",
        "}).getInfo()) "
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "{'B1': 24.42471064449399,\n",
            " 'B2': 22.57720943212569,\n",
            " 'B3': 20.919795223268885,\n",
            " 'B4': 53.67924806897354,\n",
            " 'B5': 34.62817356591265,\n",
            " 'B6_VCID_2': 198.17174001586343,\n",
            " 'B7': 21.361143212564883}\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "TPsluyew0mKg",
        "colab_type": "text"
      },
      "source": [
        "In general, specifying the scale is sufficient and results in more readable code. Earth Engine determines which pixels to input to the reducer by first rasterizing the region. If a scale is specified without a CRS, the region is rasterized in the image's native projection scaled to the specified resolution. If both a CRS and scale are specified, the region is rasterized based on them. Pixels are ‘in’ the region if their centroid is covered by the region at the specified scale and projection.\n",
        "\n",
        "The `maxPixels` parameter is needed to get the computation to succeed. If this parameter is left out of the example, an error is returned, which looks something like:\n",
        "\n",
        "\n",
        "\n",
        "```\n",
        "Dictionary (Error)\n",
        "  Image.reduceRegion: Too many pixels in the region. Found 527001545, but only 10000000 allowed.\n",
        "```\n",
        "\n",
        "\n",
        "There are multiple options to get past these errors: increase maxPixels, as in the example, increase the scale, or set bestEffort to true, which automatically computes a new (larger) scale such that maxPixels is not exceeded. If you do not specify maxPixels, the default value is used."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "MegsppPU0844",
        "colab_type": "text"
      },
      "source": [
        "# 4. Statistics of Image Regions\n",
        "\n",
        "To get image statistics in multiple regions stored in a `FeatureCollection`, you can use `image.reduceRegions()` to reduce multiple regions at once. The input to `reduceRegions()` is an Image and a `FeatureCollection`. The output is another `FeatureCollection` with the `reduceRegions()` output set as properties on each `Feature`. In this example, means of the Landsat 7 annual composite bands in each feature geometry will be added as properties to the input features:\n"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "Yq6bcT8d1Uva",
        "colab_type": "code",
        "outputId": "48fe5161-4700-4e00-9079-d6dc299c513d",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 791
        }
      },
      "source": [
        "# Load input imagery: Landsat 7 5-year composite.\n",
        "image = ee.Image('LANDSAT/LE7_TOA_5YEAR/2008_2012')\n",
        "\n",
        "# Load a FeatureCollection of counties in Maine.\n",
        "maineCounties = ee.FeatureCollection('ft:1S4EB6319wWW2sWQDPhDvmSBIVrD3iEmCLYB7nMM')\\\n",
        "                  .filter(ee.Filter.eq('StateName', 'Maine'))\n",
        "\n",
        "# Add reducer output to the Features in the collection.\n",
        "maineMeansFeatures = image.reduceRegions(**{\n",
        "  'collection': maineCounties,\n",
        "  'reducer': ee.Reducer.mean(),\n",
        "  'scale': 30,\n",
        "})\n",
        "\n",
        "# Print the first feature, to illustrate the result.\n",
        "pprint(ee.Feature(maineMeansFeatures.first()).select(image.bandNames()).getInfo())"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "{'geometry': {'coordinates': [[[-70.02323189999998, 44.134471999999995],\n",
            "                               [-70.021187, 44.158581],\n",
            "                               [-70.01097100000001, 44.15873299999999],\n",
            "                               [-70.006828, 44.17503],\n",
            "                               [-69.998047, 44.172485],\n",
            "                               [-69.993637, 44.182384],\n",
            "                               [-70.075027, 44.208988],\n",
            "                               [-70.074059, 44.291981],\n",
            "                               [-70.121117, 44.374111],\n",
            "                               [-70.10193599999998, 44.38496000000001],\n",
            "                               [-70.1249239, 44.486477],\n",
            "                               [-70.1996379, 44.479504],\n",
            "                               [-70.2317659, 44.46626700000001],\n",
            "                               [-70.273293, 44.445076],\n",
            "                               [-70.260872, 44.36852999999999],\n",
            "                               [-70.319565, 44.21826599999999],\n",
            "                               [-70.48082, 44.062126],\n",
            "                               [-70.4646, 44.018845],\n",
            "                               [-70.402222, 43.995280999999984],\n",
            "                               [-70.389084, 44.00312790000002],\n",
            "                               [-70.36367, 43.990582],\n",
            "                               [-70.310783, 44.039268],\n",
            "                               [-70.19104, 43.96111700000001],\n",
            "                               [-70.195488, 43.949848],\n",
            "                               [-70.111496, 43.917774],\n",
            "                               [-70.089966, 43.9385679],\n",
            "                               [-70.073204, 43.93169],\n",
            "                               [-70.034546, 43.9733919],\n",
            "                               [-70.038307, 43.985359],\n",
            "                               [-70.02182, 44.00629000000001],\n",
            "                               [-70.033302, 44.027611],\n",
            "                               [-70.018974, 44.044052],\n",
            "                               [-69.99940499999998, 44.127827],\n",
            "                               [-70.02323189999998, 44.134471999999995]]],\n",
            "              'type': 'Polygon'},\n",
            " 'properties': {'B1': 23.920488107254148,\n",
            "                'B2': 20.259500514380505,\n",
            "                'B3': 13.907231554387497,\n",
            "                'B4': 70.0311093317067,\n",
            "                'B5': 34.66746886242588,\n",
            "                'B6_VCID_2': 190.2679917801306,\n",
            "                'B7': 13.95038961201759},\n",
            " 'type': 'Feature'}\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "F5-4Y7H02uDW",
        "colab_type": "text"
      },
      "source": [
        "# 5. Statistics of Image Neighborhoods\n",
        "\n",
        "Rather than specifying a region over which to perform a reduction, it is also possible to specify a neighborhood in which to apply a reducer. To reduce image neighborhoods, use `image.reduceNeighborhood()`. In this case, the reduction will occur in a sliding window over the input image, with the window size and shape specified by an `ee.Kernel`. The output of `reduceNeighborhood()` will be another image, with each pixel value representing the output of the reduction in a neighborhood around that pixel in the input image. Figure 3 illustrates this type of reduction.\n",
        "\n",
        "<center>\n",
        "<img src=\"https://developers.google.com/earth-engine/images/Reduce_Neighborhood.png\">  \n",
        "</center>  \n",
        "\n",
        "<center>\n",
        "Figure 3. Illustration of `reduceNeighborhood()`, where the reducer is applied in a kernel.\n",
        "</center>  \n",
        "\n",
        "\n",
        "For example, consider using National Agriculture Imagery Program (NAIP) imagery to quantify landscape differences resulting from logging in the California redwood forests. Specifically, use standard deviation (SD) in a neighborhood to represent the difference in texture between the logged area and the protected area. For example, to get texture of a NAIP Normalized Difference Vegetation Index (NDVI) image, use reduceNeighborhood() to compute SD in a neighborhood defined by a kernel:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "w7YYqNYd4MqQ",
        "colab_type": "code",
        "outputId": "9b66c6c9-9108-49d4-fd64-e07bd26ddc3b",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 559
        }
      },
      "source": [
        "# Define a region in the redwood forest.\n",
        "redwoods = ee.Geometry.Rectangle(-124.0665, 41.0739, -123.934, 41.2029)\n",
        "\n",
        "# Load input NAIP imagery and build a mosaic.\n",
        "naipCollection = ee.ImageCollection('USDA/NAIP/DOQQ')\\\n",
        "                   .filterBounds(redwoods)\\\n",
        "                   .filterDate('2012-01-01', '2012-12-31')\n",
        "\n",
        "naip = naipCollection.mosaic()\n",
        "\n",
        "# Compute NDVI from the NAIP imagery.\n",
        "naipNDVI = naip.normalizedDifference(['N', 'R'])\n",
        "\n",
        "# Compute standard deviation (SD) as texture of the NDVI.\n",
        "texture = naipNDVI.reduceNeighborhood(**{\n",
        "  'reducer': ee.Reducer.stdDev(),\n",
        "  'kernel': ee.Kernel.circle(7),\n",
        "})\n",
        "\n",
        "# Display the results.\n",
        "center = redwoods.centroid().getInfo()['coordinates']\n",
        "center.reverse()\n",
        "dicc ={'NAIP input imagery': naip.getMapId(),\n",
        "       'NDVI': naipNDVI.getMapId({'min': -1, 'max': 1, 'palette': ['FF0000', '00FF00']}),\n",
        "       'SD of NDVI':texture.getMapId({'min': 0, 'max': 0.3})}\n",
        "Mapdisplay(center,dicc,zoom_start=12)"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/html": [
              "<div style=\"width:100%;\"><div style=\"position:relative;width:100%;height:0;padding-bottom:60%;\"><iframe src=\"data:text/html;charset=utf-8;base64,PCFET0NUWVBFIGh0bWw+CjxoZWFkPiAgICAKICAgIDxtZXRhIGh0dHAtZXF1aXY9ImNvbnRlbnQtdHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PVVURi04IiAvPgogICAgPHNjcmlwdD5MX1BSRUZFUl9DQU5WQVM9ZmFsc2U7IExfTk9fVE9VQ0g9ZmFsc2U7IExfRElTQUJMRV8zRD1mYWxzZTs8L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS40LjAvZGlzdC9sZWFmbGV0LmpzIj48L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2NvZGUuanF1ZXJ5LmNvbS9qcXVlcnktMS4xMi40Lm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvanMvYm9vdHN0cmFwLm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9jZG5qcy5jbG91ZGZsYXJlLmNvbS9hamF4L2xpYnMvTGVhZmxldC5hd2Vzb21lLW1hcmtlcnMvMi4wLjIvbGVhZmxldC5hd2Vzb21lLW1hcmtlcnMuanMiPjwvc2NyaXB0PgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS40LjAvZGlzdC9sZWFmbGV0LmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9jc3MvYm9vdHN0cmFwLm1pbi5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvY3NzL2Jvb3RzdHJhcC10aGVtZS5taW4uY3NzIi8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vbWF4Y2RuLmJvb3RzdHJhcGNkbi5jb20vZm9udC1hd2Vzb21lLzQuNi4zL2Nzcy9mb250LWF3ZXNvbWUubWluLmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2NkbmpzLmNsb3VkZmxhcmUuY29tL2FqYXgvbGlicy9MZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy8yLjAuMi9sZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9yYXdjZG4uZ2l0aGFjay5jb20vcHl0aG9uLXZpc3VhbGl6YXRpb24vZm9saXVtL21hc3Rlci9mb2xpdW0vdGVtcGxhdGVzL2xlYWZsZXQuYXdlc29tZS5yb3RhdGUuY3NzIi8+CiAgICA8c3R5bGU+aHRtbCwgYm9keSB7d2lkdGg6IDEwMCU7aGVpZ2h0OiAxMDAlO21hcmdpbjogMDtwYWRkaW5nOiAwO308L3N0eWxlPgogICAgPHN0eWxlPiNtYXAge3Bvc2l0aW9uOmFic29sdXRlO3RvcDowO2JvdHRvbTowO3JpZ2h0OjA7bGVmdDowO308L3N0eWxlPgogICAgCiAgICA8bWV0YSBuYW1lPSJ2aWV3cG9ydCIgY29udGVudD0id2lkdGg9ZGV2aWNlLXdpZHRoLAogICAgICAgIGluaXRpYWwtc2NhbGU9MS4wLCBtYXhpbXVtLXNjYWxlPTEuMCwgdXNlci1zY2FsYWJsZT1ubyIgLz4KICAgIDxzdHlsZT4jbWFwXzZhM2MyNTcwMmY3MDQwMmQ4ZTc2M2EyMDQ5MzY4MmM5IHsKICAgICAgICBwb3NpdGlvbjogcmVsYXRpdmU7CiAgICAgICAgd2lkdGg6IDEwMC4wJTsKICAgICAgICBoZWlnaHQ6IDEwMC4wJTsKICAgICAgICBsZWZ0OiAwLjAlOwogICAgICAgIHRvcDogMC4wJTsKICAgICAgICB9CiAgICA8L3N0eWxlPgo8L2hlYWQ+Cjxib2R5PiAgICAKICAgIAogICAgPGRpdiBjbGFzcz0iZm9saXVtLW1hcCIgaWQ9Im1hcF82YTNjMjU3MDJmNzA0MDJkOGU3NjNhMjA0OTM2ODJjOSIgPjwvZGl2Pgo8L2JvZHk+CjxzY3JpcHQ+ICAgIAogICAgCiAgICAKICAgICAgICB2YXIgYm91bmRzID0gbnVsbDsKICAgIAoKICAgIHZhciBtYXBfNmEzYzI1NzAyZjcwNDAyZDhlNzYzYTIwNDkzNjgyYzkgPSBMLm1hcCgKICAgICAgICAnbWFwXzZhM2MyNTcwMmY3MDQwMmQ4ZTc2M2EyMDQ5MzY4MmM5JywgewogICAgICAgIGNlbnRlcjogWzQxLjEzODM5NzgzNDYyMDg3LCAtMTI0LjAwMDI1MDAwMDAwMDM1XSwKICAgICAgICB6b29tOiAxMiwKICAgICAgICBtYXhCb3VuZHM6IGJvdW5kcywKICAgICAgICBsYXllcnM6IFtdLAogICAgICAgIHdvcmxkQ29weUp1bXA6IGZhbHNlLAogICAgICAgIGNyczogTC5DUlMuRVBTRzM4NTcsCiAgICAgICAgem9vbUNvbnRyb2w6IHRydWUsCiAgICAgICAgfSk7CgoKICAgIAogICAgdmFyIHRpbGVfbGF5ZXJfNTBhZWMzN2E5MDE4NGZmNjgzZTBlZWY4YmMzZWY0MzkgPSBMLnRpbGVMYXllcigKICAgICAgICAnaHR0cHM6Ly97c30udGlsZS5vcGVuc3RyZWV0bWFwLm9yZy97en0ve3h9L3t5fS5wbmcnLAogICAgICAgIHsKICAgICAgICAiYXR0cmlidXRpb24iOiBudWxsLAogICAgICAgICJkZXRlY3RSZXRpbmEiOiBmYWxzZSwKICAgICAgICAibWF4TmF0aXZlWm9vbSI6IDE4LAogICAgICAgICJtYXhab29tIjogMTgsCiAgICAgICAgIm1pblpvb20iOiAwLAogICAgICAgICJub1dyYXAiOiBmYWxzZSwKICAgICAgICAib3BhY2l0eSI6IDEsCiAgICAgICAgInN1YmRvbWFpbnMiOiAiYWJjIiwKICAgICAgICAidG1zIjogZmFsc2UKfSkuYWRkVG8obWFwXzZhM2MyNTcwMmY3MDQwMmQ4ZTc2M2EyMDQ5MzY4MmM5KTsKICAgIHZhciB0aWxlX2xheWVyX2RmMzY5YWI3Y2ZkZjQ3NWQ5OWIwYzQxNTgzNzhiNzMwID0gTC50aWxlTGF5ZXIoCiAgICAgICAgJ2h0dHBzOi8vZWFydGhlbmdpbmUuZ29vZ2xlYXBpcy5jb20vbWFwLzUxYmY3N2MyMDY4NDU1ZTE2NzUzOGExY2UzMTY4MmM2L3t6fS97eH0ve3l9P3Rva2VuPTM4YmRiYzk4ZWJlNGY3ZjMxYzNiNTc3ZWM3YWQxNWNjJywKICAgICAgICB7CiAgICAgICAgImF0dHJpYnV0aW9uIjogIkdvb2dsZSBFYXJ0aCBFbmdpbmUiLAogICAgICAgICJkZXRlY3RSZXRpbmEiOiBmYWxzZSwKICAgICAgICAibWF4TmF0aXZlWm9vbSI6IDE4LAogICAgICAgICJtYXhab29tIjogMTgsCiAgICAgICAgIm1pblpvb20iOiAwLAogICAgICAgICJub1dyYXAiOiBmYWxzZSwKICAgICAgICAib3BhY2l0eSI6IDEsCiAgICAgICAgInN1YmRvbWFpbnMiOiAiYWJjIiwKICAgICAgICAidG1zIjogZmFsc2UKfSkuYWRkVG8obWFwXzZhM2MyNTcwMmY3MDQwMmQ4ZTc2M2EyMDQ5MzY4MmM5KTsKICAgIHZhciB0aWxlX2xheWVyXzExMWE1MTVjZTEwZDRmMGU5YWYxY2QxNGI2ZDg0YWMzID0gTC50aWxlTGF5ZXIoCiAgICAgICAgJ2h0dHBzOi8vZWFydGhlbmdpbmUuZ29vZ2xlYXBpcy5jb20vbWFwLzc2MWUwNDFmNjY5Yjk0NDhkZTAyODJhODE1ZTNhZjExL3t6fS97eH0ve3l9P3Rva2VuPTU0ZjRiNWNiNmVjNjY1ODMwYmY4Y2JlNGE0Y2QzMjljJywKICAgICAgICB7CiAgICAgICAgImF0dHJpYnV0aW9uIjogIkdvb2dsZSBFYXJ0aCBFbmdpbmUiLAogICAgICAgICJkZXRlY3RSZXRpbmEiOiBmYWxzZSwKICAgICAgICAibWF4TmF0aXZlWm9vbSI6IDE4LAogICAgICAgICJtYXhab29tIjogMTgsCiAgICAgICAgIm1pblpvb20iOiAwLAogICAgICAgICJub1dyYXAiOiBmYWxzZSwKICAgICAgICAib3BhY2l0eSI6IDEsCiAgICAgICAgInN1YmRvbWFpbnMiOiAiYWJjIiwKICAgICAgICAidG1zIjogZmFsc2UKfSkuYWRkVG8obWFwXzZhM2MyNTcwMmY3MDQwMmQ4ZTc2M2EyMDQ5MzY4MmM5KTsKICAgIHZhciB0aWxlX2xheWVyX2M2ZTE2OWU3Y2FkODRhNGI4ZDMzMTg5ODIzYjBlNWE0ID0gTC50aWxlTGF5ZXIoCiAgICAgICAgJ2h0dHBzOi8vZWFydGhlbmdpbmUuZ29vZ2xlYXBpcy5jb20vbWFwLzBiMGEwZjdlMTA3MmY4NDc4ZjgzMzVjZmUxMjY1N2YwL3t6fS97eH0ve3l9P3Rva2VuPTY2YjZlNDEzNTZlNDk4MDMxYzAzNTY0NTE4MzEzNTIzJywKICAgICAgICB7CiAgICAgICAgImF0dHJpYnV0aW9uIjogIkdvb2dsZSBFYXJ0aCBFbmdpbmUiLAogICAgICAgICJkZXRlY3RSZXRpbmEiOiBmYWxzZSwKICAgICAgICAibWF4TmF0aXZlWm9vbSI6IDE4LAogICAgICAgICJtYXhab29tIjogMTgsCiAgICAgICAgIm1pblpvb20iOiAwLAogICAgICAgICJub1dyYXAiOiBmYWxzZSwKICAgICAgICAib3BhY2l0eSI6IDEsCiAgICAgICAgInN1YmRvbWFpbnMiOiAiYWJjIiwKICAgICAgICAidG1zIjogZmFsc2UKfSkuYWRkVG8obWFwXzZhM2MyNTcwMmY3MDQwMmQ4ZTc2M2EyMDQ5MzY4MmM5KTsKICAgIAogICAgICAgICAgICB2YXIgbGF5ZXJfY29udHJvbF9kYjAwMTM0ZmMwOGQ0ODZjYmE4OTUzNGNlN2Y4YzJmMCA9IHsKICAgICAgICAgICAgICAgIGJhc2VfbGF5ZXJzIDogeyAib3BlbnN0cmVldG1hcCIgOiB0aWxlX2xheWVyXzUwYWVjMzdhOTAxODRmZjY4M2UwZWVmOGJjM2VmNDM5LCB9LAogICAgICAgICAgICAgICAgb3ZlcmxheXMgOiB7ICJOQUlQIGlucHV0IGltYWdlcnkiIDogdGlsZV9sYXllcl9kZjM2OWFiN2NmZGY0NzVkOTliMGM0MTU4Mzc4YjczMCwiTkRWSSIgOiB0aWxlX2xheWVyXzExMWE1MTVjZTEwZDRmMGU5YWYxY2QxNGI2ZDg0YWMzLCJTRCBvZiBORFZJIiA6IHRpbGVfbGF5ZXJfYzZlMTY5ZTdjYWQ4NGE0YjhkMzMxODk4MjNiMGU1YTQsIH0KICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgIEwuY29udHJvbC5sYXllcnMoCiAgICAgICAgICAgICAgICBsYXllcl9jb250cm9sX2RiMDAxMzRmYzA4ZDQ4NmNiYTg5NTM0Y2U3ZjhjMmYwLmJhc2VfbGF5ZXJzLAogICAgICAgICAgICAgICAgbGF5ZXJfY29udHJvbF9kYjAwMTM0ZmMwOGQ0ODZjYmE4OTUzNGNlN2Y4YzJmMC5vdmVybGF5cywKICAgICAgICAgICAgICAgIHtwb3NpdGlvbjogJ3RvcHJpZ2h0JywKICAgICAgICAgICAgICAgICBjb2xsYXBzZWQ6IHRydWUsCiAgICAgICAgICAgICAgICAgYXV0b1pJbmRleDogdHJ1ZQogICAgICAgICAgICAgICAgfSkuYWRkVG8obWFwXzZhM2MyNTcwMmY3MDQwMmQ4ZTc2M2EyMDQ5MzY4MmM5KTsKICAgICAgICAgICAgCiAgICAgICAgCjwvc2NyaXB0Pg==\" style=\"position:absolute;width:100%;height:100%;left:0;top:0;border:none !important;\" allowfullscreen webkitallowfullscreen mozallowfullscreen></iframe></div></div>"
            ],
            "text/plain": [
              "<folium.folium.Map at 0x7fd399370828>"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 74
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "gc10yKO37cjQ",
        "colab_type": "text"
      },
      "source": [
        "# 6. Statistics of FeatureCollection Columns\n",
        "\n",
        "To reduce properties of features in a `FeatureCollection`, use `featureCollection.reduceColumns()`. Consider the following toy example:\n"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "fo76QdrF768P",
        "colab_type": "code",
        "outputId": "1c09f1c6-f467-4f1c-c753-585cedbda0c0",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 35
        }
      },
      "source": [
        "# Make a toy FeatureCollection.\n",
        "aFeatureCollection = ee.FeatureCollection([\n",
        "  ee.Feature(None, {'foo': 1, 'weight': 1}),\n",
        "  ee.Feature(None, {'foo': 2, 'weight': 2}),\n",
        "  ee.Feature(None, {'foo': 3, 'weight': 3}),\n",
        "])\n",
        "\n",
        "# Compute a weighted mean and display it.\n",
        "pprint(aFeatureCollection.reduceColumns(**{\n",
        "  'reducer': ee.Reducer.mean(),\n",
        "  'selectors': ['foo'],\n",
        "  'weightSelectors': ['weight']\n",
        "}).getInfo())"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "{'mean': 2.3333333333333335}\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "FPMrXnrd8M6t",
        "colab_type": "text"
      },
      "source": [
        "As a more complex example, consider a `FeatureCollection` of US counties with census data as attributes. The variables of interest are total population and total housing units. You can get their sum(s) by supplying a summing reducer argument to `reduceColumns()` and printing the result:"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "xqXf4rTp8Maf",
        "colab_type": "code",
        "outputId": "a52d3cfe-1249-43e7-dbce-0ee7d81ef317",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 577
        }
      },
      "source": [
        "# Load a collection of US counties with census data properties and display it.\n",
        "counties = ee.FeatureCollection('ft:1S4EB6319wWW2sWQDPhDvmSBIVrD3iEmCLYB7nMM')\n",
        "\n",
        "# Compute sums of the specified properties and print the resultant Dictionary.\n",
        "sums = counties.filter(ee.Filter.And(ee.Filter.neq('Census 2000 Population', None),\n",
        "                                     ee.Filter.neq('Census 2000 Housing Units', None)))\\\n",
        "               .reduceColumns(**{'reducer': ee.Reducer.sum().repeat(2),\n",
        "                               'selectors': ['Census 2000 Population', 'Census 2000 Housing Units']})\n",
        "print(sums.getInfo())\n",
        "\n",
        "# Display with folium!\n",
        "center = counties.geometry().centroid().getInfo()['coordinates']\n",
        "center.reverse()\n",
        "Mapdisplay(center,{'Census':counties.getMapId()},zoom_start=5)"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "{'sum': [279162260.0, 115048233.0]}\n"
          ],
          "name": "stdout"
        },
        {
          "output_type": "execute_result",
          "data": {
            "text/html": [
              "<div style=\"width:100%;\"><div style=\"position:relative;width:100%;height:0;padding-bottom:60%;\"><iframe src=\"data:text/html;charset=utf-8;base64,PCFET0NUWVBFIGh0bWw+CjxoZWFkPiAgICAKICAgIDxtZXRhIGh0dHAtZXF1aXY9ImNvbnRlbnQtdHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PVVURi04IiAvPgogICAgPHNjcmlwdD5MX1BSRUZFUl9DQU5WQVM9ZmFsc2U7IExfTk9fVE9VQ0g9ZmFsc2U7IExfRElTQUJMRV8zRD1mYWxzZTs8L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS40LjAvZGlzdC9sZWFmbGV0LmpzIj48L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2NvZGUuanF1ZXJ5LmNvbS9qcXVlcnktMS4xMi40Lm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvanMvYm9vdHN0cmFwLm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9jZG5qcy5jbG91ZGZsYXJlLmNvbS9hamF4L2xpYnMvTGVhZmxldC5hd2Vzb21lLW1hcmtlcnMvMi4wLjIvbGVhZmxldC5hd2Vzb21lLW1hcmtlcnMuanMiPjwvc2NyaXB0PgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS40LjAvZGlzdC9sZWFmbGV0LmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9jc3MvYm9vdHN0cmFwLm1pbi5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvY3NzL2Jvb3RzdHJhcC10aGVtZS5taW4uY3NzIi8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vbWF4Y2RuLmJvb3RzdHJhcGNkbi5jb20vZm9udC1hd2Vzb21lLzQuNi4zL2Nzcy9mb250LWF3ZXNvbWUubWluLmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2NkbmpzLmNsb3VkZmxhcmUuY29tL2FqYXgvbGlicy9MZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy8yLjAuMi9sZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9yYXdjZG4uZ2l0aGFjay5jb20vcHl0aG9uLXZpc3VhbGl6YXRpb24vZm9saXVtL21hc3Rlci9mb2xpdW0vdGVtcGxhdGVzL2xlYWZsZXQuYXdlc29tZS5yb3RhdGUuY3NzIi8+CiAgICA8c3R5bGU+aHRtbCwgYm9keSB7d2lkdGg6IDEwMCU7aGVpZ2h0OiAxMDAlO21hcmdpbjogMDtwYWRkaW5nOiAwO308L3N0eWxlPgogICAgPHN0eWxlPiNtYXAge3Bvc2l0aW9uOmFic29sdXRlO3RvcDowO2JvdHRvbTowO3JpZ2h0OjA7bGVmdDowO308L3N0eWxlPgogICAgCiAgICA8bWV0YSBuYW1lPSJ2aWV3cG9ydCIgY29udGVudD0id2lkdGg9ZGV2aWNlLXdpZHRoLAogICAgICAgIGluaXRpYWwtc2NhbGU9MS4wLCBtYXhpbXVtLXNjYWxlPTEuMCwgdXNlci1zY2FsYWJsZT1ubyIgLz4KICAgIDxzdHlsZT4jbWFwXzE0NTVmM2ViMmMyNzQzMjE5MjE2ZWE2MjAwZTdiZTllIHsKICAgICAgICBwb3NpdGlvbjogcmVsYXRpdmU7CiAgICAgICAgd2lkdGg6IDEwMC4wJTsKICAgICAgICBoZWlnaHQ6IDEwMC4wJTsKICAgICAgICBsZWZ0OiAwLjAlOwogICAgICAgIHRvcDogMC4wJTsKICAgICAgICB9CiAgICA8L3N0eWxlPgo8L2hlYWQ+Cjxib2R5PiAgICAKICAgIAogICAgPGRpdiBjbGFzcz0iZm9saXVtLW1hcCIgaWQ9Im1hcF8xNDU1ZjNlYjJjMjc0MzIxOTIxNmVhNjIwMGU3YmU5ZSIgPjwvZGl2Pgo8L2JvZHk+CjxzY3JpcHQ+ICAgIAogICAgCiAgICAKICAgICAgICB2YXIgYm91bmRzID0gbnVsbDsKICAgIAoKICAgIHZhciBtYXBfMTQ1NWYzZWIyYzI3NDMyMTkyMTZlYTYyMDBlN2JlOWUgPSBMLm1hcCgKICAgICAgICAnbWFwXzE0NTVmM2ViMmMyNzQzMjE5MjE2ZWE2MjAwZTdiZTllJywgewogICAgICAgIGNlbnRlcjogWzQ0LjcwNDQ4MzM4Nzk5NzE2LCAtMTAzLjkyNTQ0NTAzMTg2ODYyXSwKICAgICAgICB6b29tOiA1LAogICAgICAgIG1heEJvdW5kczogYm91bmRzLAogICAgICAgIGxheWVyczogW10sCiAgICAgICAgd29ybGRDb3B5SnVtcDogZmFsc2UsCiAgICAgICAgY3JzOiBMLkNSUy5FUFNHMzg1NywKICAgICAgICB6b29tQ29udHJvbDogdHJ1ZSwKICAgICAgICB9KTsKCgogICAgCiAgICB2YXIgdGlsZV9sYXllcl9hMTdkZTdkMDVkOTM0MGI3OGYzY2M4YTAzMDYyMDg2ZiA9IEwudGlsZUxheWVyKAogICAgICAgICdodHRwczovL3tzfS50aWxlLm9wZW5zdHJlZXRtYXAub3JnL3t6fS97eH0ve3l9LnBuZycsCiAgICAgICAgewogICAgICAgICJhdHRyaWJ1dGlvbiI6IG51bGwsCiAgICAgICAgImRldGVjdFJldGluYSI6IGZhbHNlLAogICAgICAgICJtYXhOYXRpdmVab29tIjogMTgsCiAgICAgICAgIm1heFpvb20iOiAxOCwKICAgICAgICAibWluWm9vbSI6IDAsCiAgICAgICAgIm5vV3JhcCI6IGZhbHNlLAogICAgICAgICJvcGFjaXR5IjogMSwKICAgICAgICAic3ViZG9tYWlucyI6ICJhYmMiLAogICAgICAgICJ0bXMiOiBmYWxzZQp9KS5hZGRUbyhtYXBfMTQ1NWYzZWIyYzI3NDMyMTkyMTZlYTYyMDBlN2JlOWUpOwogICAgdmFyIHRpbGVfbGF5ZXJfYWJmNmYxYTBlNWJhNGMxM2ExOWIzNTZlNjNjYzlmNzUgPSBMLnRpbGVMYXllcigKICAgICAgICAnaHR0cHM6Ly9lYXJ0aGVuZ2luZS5nb29nbGVhcGlzLmNvbS9tYXAvZjYxNGI2ZWQ3YmFlY2ZiODQzZmRkZDcwMmU1MmVkNjQve3p9L3t4fS97eX0/dG9rZW49NDgwMWM5MDlmMTU3OWJiNTk0Y2YwYjk0MTNlODMzMmYnLAogICAgICAgIHsKICAgICAgICAiYXR0cmlidXRpb24iOiAiR29vZ2xlIEVhcnRoIEVuZ2luZSIsCiAgICAgICAgImRldGVjdFJldGluYSI6IGZhbHNlLAogICAgICAgICJtYXhOYXRpdmVab29tIjogMTgsCiAgICAgICAgIm1heFpvb20iOiAxOCwKICAgICAgICAibWluWm9vbSI6IDAsCiAgICAgICAgIm5vV3JhcCI6IGZhbHNlLAogICAgICAgICJvcGFjaXR5IjogMSwKICAgICAgICAic3ViZG9tYWlucyI6ICJhYmMiLAogICAgICAgICJ0bXMiOiBmYWxzZQp9KS5hZGRUbyhtYXBfMTQ1NWYzZWIyYzI3NDMyMTkyMTZlYTYyMDBlN2JlOWUpOwogICAgCiAgICAgICAgICAgIHZhciBsYXllcl9jb250cm9sX2IyYzA4OGE3ZTZhZDQ5MTNhNzRiM2Q3MDkwMjgwYjc5ID0gewogICAgICAgICAgICAgICAgYmFzZV9sYXllcnMgOiB7ICJvcGVuc3RyZWV0bWFwIiA6IHRpbGVfbGF5ZXJfYTE3ZGU3ZDA1ZDkzNDBiNzhmM2NjOGEwMzA2MjA4NmYsIH0sCiAgICAgICAgICAgICAgICBvdmVybGF5cyA6IHsgIkNlbnN1cyIgOiB0aWxlX2xheWVyX2FiZjZmMWEwZTViYTRjMTNhMTliMzU2ZTYzY2M5Zjc1LCB9CiAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICBMLmNvbnRyb2wubGF5ZXJzKAogICAgICAgICAgICAgICAgbGF5ZXJfY29udHJvbF9iMmMwODhhN2U2YWQ0OTEzYTc0YjNkNzA5MDI4MGI3OS5iYXNlX2xheWVycywKICAgICAgICAgICAgICAgIGxheWVyX2NvbnRyb2xfYjJjMDg4YTdlNmFkNDkxM2E3NGIzZDcwOTAyODBiNzkub3ZlcmxheXMsCiAgICAgICAgICAgICAgICB7cG9zaXRpb246ICd0b3ByaWdodCcsCiAgICAgICAgICAgICAgICAgY29sbGFwc2VkOiB0cnVlLAogICAgICAgICAgICAgICAgIGF1dG9aSW5kZXg6IHRydWUKICAgICAgICAgICAgICAgIH0pLmFkZFRvKG1hcF8xNDU1ZjNlYjJjMjc0MzIxOTIxNmVhNjIwMGU3YmU5ZSk7CiAgICAgICAgICAgIAogICAgICAgIAo8L3NjcmlwdD4=\" style=\"position:absolute;width:100%;height:100%;left:0;top:0;border:none !important;\" allowfullscreen webkitallowfullscreen mozallowfullscreen></iframe></div></div>"
            ],
            "text/plain": [
              "<folium.folium.Map at 0x7fd3993a2978>"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 94
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "f8r4aT1F95MD",
        "colab_type": "text"
      },
      "source": [
        "Note that because feature collections may contain missing data (unlike images, which handle missing data with masks), the input needs to be pre-filtered to eliminate null values.\n",
        "\n",
        "An error that looks something like the following may be thrown as a result of attributes with **None** values:\n",
        "\n",
        "```\n",
        "Dictionary (Error)\n",
        "  Collection.reduceColumns: Can't set input 0 of Reducer(reducer=SUM, count=2) to .:\n",
        "  Input must be a scalar number.\n",
        "```  \n",
        "Also note that unlike `imageCollection.reduce()`, in which reducers are automatically repeated for each band, reducers on a `FeatureCollection` must be explicitly repeated using `repeat()`. Specifically, repeat the reducer m times for m inputs. The following error may be thrown as a result of not repeating the reducer:\n",
        "\n",
        "```\n",
        "Dictionary (Error)\n",
        "  Collection.reduceColumns: Need 1 inputs for <Reducer>, got 2.\n",
        "```\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "DIA-XFQc-vpL",
        "colab_type": "text"
      },
      "source": [
        "# 7. Raster to Vector Conversion\n",
        "\n",
        "To convert from an `Image` (raster) to a `FeatureCollection` (vector) data type, use `image.reduceToVectors()`. This is the primary mechanism for vectorization in Earth Engine, and can be useful for generating regions for input to other types of reducer. The `reduceToVectors()` method creates polygon edges (optionally centroids or bounding boxes instead) at the boundary of homogeneous groups of connected pixels.\n",
        "\n",
        "For example, consider a 2012 nightlights image of Japan. Let the nightlights digital number serve as a proxy for development intensity. Define zones using arbitrary thresholds on the nightlights, combine the zones into a single-band image, vectorize the zones using `reduceToVectors()`:"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "A1ehJ4pQ_KtJ",
        "colab_type": "code",
        "outputId": "070e67d0-4d4a-4954-93a7-bd2c2c14a3f1",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 35
        }
      },
      "source": [
        "# Load a Japan boundary from the Large Scale International Boundary dataset.\n",
        "japan = ee.FeatureCollection('USDOS/LSIB_SIMPLE/2017')\\\n",
        "          .filter(ee.Filter.eq('country_na', 'Japan'))\n",
        "\n",
        "# Load a 2012 nightlights image, clipped to the Japan border.\n",
        "nl2012 = ee.Image('NOAA/DMSP-OLS/NIGHTTIME_LIGHTS/F182012')\\\n",
        "           .select('stable_lights')\\\n",
        "           .clipToCollection(japan)\n",
        "\n",
        "# Define arbitrary thresholds on the 6-bit nightlights image.\n",
        "zones = nl2012.gt(30)\\\n",
        "              .add(nl2012.gt(55))\\\n",
        "              .add(nl2012.gt(62))\\\n",
        "              .updateMask(zones.neq(0))\n",
        "\n",
        "\n",
        "# Convert the zones of the thresholded nightlights to vectors.\n",
        "vectors = zones.addBands(nl2012).reduceToVectors(**{\n",
        "  'geometry': japan,\n",
        "  'crs': nl2012.projection(),\n",
        "  'scale': 1000,\n",
        "  'geometryType': 'polygon',\n",
        "  'eightConnected': False,\n",
        "  'labelProperty': 'zone',\n",
        "  'reducer': ee.Reducer.mean()\n",
        "})\n",
        "\n",
        "display = ee.Image(0).updateMask(0).paint(vectors, '000000', 3)\n",
        "\n",
        "\n",
        "# Display the thresholds.\n",
        "center = [35.712, 139.6225]\n",
        "zones_tk = zones.getMapId({'min': 1, 'max': 3, 'palette': ['0000FF', '00FF00', 'FF0000']})\n",
        "display_tk = display.getMapId({'palette': '000000'})\n",
        "\n",
        "Mapdisplay(center,{'raster':zones_tk,'vectors':display_tk},zoom_start=9)\n"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "<ee.image.Image at 0x7fd39932fdd8>"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 109
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "lwh7meRSDGQ8",
        "colab_type": "text"
      },
      "source": [
        "Note that the first band in the input is used to identify homogeneous regions and the remaining bands are reduced according to the provided reducer, the output of which is added as a property to the resultant vectors. The `geometry` parameter specifies the extent over which the vectors should be created. In general, it is good practice to specify a minimal zone over which to create vectors. It is also good practice to specify the `scale` and `crs` to avoid ambiguity. The output type is `‘polygon’` where the polygons are formed from homogeneous zones of four-connected neighbors (i.e. `eightConnected` is false). The last two parameters, `labelProperty` and reducer, specify that the output polygons should receive a property with the zone label and the mean of the nightlights band(s), respectively."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "03kGP-85Dy9M",
        "colab_type": "text"
      },
      "source": [
        "# 8. Vector to Raster Conversion\n",
        "\n",
        "Vector to raster conversion in Earth Engine is handled by the `featureCollection.reduceToImage()` method. This method assigns pixels under each feature the value of the specified property. This example uses the counties data to create an image representing the population of each county:"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "PCa_nFB5DZCh",
        "colab_type": "code",
        "outputId": "dcf7c710-0148-452e-9419-6ada1f8e8a85",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 559
        }
      },
      "source": [
        "# Load a collection of US counties with census data properties.\n",
        "counties = ee.FeatureCollection('ft:1S4EB6319wWW2sWQDPhDvmSBIVrD3iEmCLYB7nMM')\n",
        "\n",
        "# Make an image out of the population attribute and display it.\n",
        "popImage = counties.filter(ee.Filter.neq('Census 2000 Population', None))\\\n",
        "                   .reduceToImage(**{'properties': ['Census 2000 Population'],\n",
        "                                     'reducer': ee.Reducer.first()})\n",
        "center = [40.38, -99.976]\n",
        "popImage_tk = popImage.getMapId({'min': 0, 'max': 1000000,\n",
        "                                 'palette': ['0000FF', '00FF00', '00FFFF', 'FF0000']})\n",
        "Mapdisplay(center, {'popImage':popImage_tk}, zoom_start=5)"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/html": [
              "<div style=\"width:100%;\"><div style=\"position:relative;width:100%;height:0;padding-bottom:60%;\"><iframe src=\"data:text/html;charset=utf-8;base64,PCFET0NUWVBFIGh0bWw+CjxoZWFkPiAgICAKICAgIDxtZXRhIGh0dHAtZXF1aXY9ImNvbnRlbnQtdHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PVVURi04IiAvPgogICAgPHNjcmlwdD5MX1BSRUZFUl9DQU5WQVM9ZmFsc2U7IExfTk9fVE9VQ0g9ZmFsc2U7IExfRElTQUJMRV8zRD1mYWxzZTs8L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS40LjAvZGlzdC9sZWFmbGV0LmpzIj48L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2NvZGUuanF1ZXJ5LmNvbS9qcXVlcnktMS4xMi40Lm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvanMvYm9vdHN0cmFwLm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9jZG5qcy5jbG91ZGZsYXJlLmNvbS9hamF4L2xpYnMvTGVhZmxldC5hd2Vzb21lLW1hcmtlcnMvMi4wLjIvbGVhZmxldC5hd2Vzb21lLW1hcmtlcnMuanMiPjwvc2NyaXB0PgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS40LjAvZGlzdC9sZWFmbGV0LmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9jc3MvYm9vdHN0cmFwLm1pbi5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvY3NzL2Jvb3RzdHJhcC10aGVtZS5taW4uY3NzIi8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vbWF4Y2RuLmJvb3RzdHJhcGNkbi5jb20vZm9udC1hd2Vzb21lLzQuNi4zL2Nzcy9mb250LWF3ZXNvbWUubWluLmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2NkbmpzLmNsb3VkZmxhcmUuY29tL2FqYXgvbGlicy9MZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy8yLjAuMi9sZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9yYXdjZG4uZ2l0aGFjay5jb20vcHl0aG9uLXZpc3VhbGl6YXRpb24vZm9saXVtL21hc3Rlci9mb2xpdW0vdGVtcGxhdGVzL2xlYWZsZXQuYXdlc29tZS5yb3RhdGUuY3NzIi8+CiAgICA8c3R5bGU+aHRtbCwgYm9keSB7d2lkdGg6IDEwMCU7aGVpZ2h0OiAxMDAlO21hcmdpbjogMDtwYWRkaW5nOiAwO308L3N0eWxlPgogICAgPHN0eWxlPiNtYXAge3Bvc2l0aW9uOmFic29sdXRlO3RvcDowO2JvdHRvbTowO3JpZ2h0OjA7bGVmdDowO308L3N0eWxlPgogICAgCiAgICA8bWV0YSBuYW1lPSJ2aWV3cG9ydCIgY29udGVudD0id2lkdGg9ZGV2aWNlLXdpZHRoLAogICAgICAgIGluaXRpYWwtc2NhbGU9MS4wLCBtYXhpbXVtLXNjYWxlPTEuMCwgdXNlci1zY2FsYWJsZT1ubyIgLz4KICAgIDxzdHlsZT4jbWFwX2NjODE0NTVkOTc2MTQzZmU5MzQyYTliMDA5NjhmMGJhIHsKICAgICAgICBwb3NpdGlvbjogcmVsYXRpdmU7CiAgICAgICAgd2lkdGg6IDEwMC4wJTsKICAgICAgICBoZWlnaHQ6IDEwMC4wJTsKICAgICAgICBsZWZ0OiAwLjAlOwogICAgICAgIHRvcDogMC4wJTsKICAgICAgICB9CiAgICA8L3N0eWxlPgo8L2hlYWQ+Cjxib2R5PiAgICAKICAgIAogICAgPGRpdiBjbGFzcz0iZm9saXVtLW1hcCIgaWQ9Im1hcF9jYzgxNDU1ZDk3NjE0M2ZlOTM0MmE5YjAwOTY4ZjBiYSIgPjwvZGl2Pgo8L2JvZHk+CjxzY3JpcHQ+ICAgIAogICAgCiAgICAKICAgICAgICB2YXIgYm91bmRzID0gbnVsbDsKICAgIAoKICAgIHZhciBtYXBfY2M4MTQ1NWQ5NzYxNDNmZTkzNDJhOWIwMDk2OGYwYmEgPSBMLm1hcCgKICAgICAgICAnbWFwX2NjODE0NTVkOTc2MTQzZmU5MzQyYTliMDA5NjhmMGJhJywgewogICAgICAgIGNlbnRlcjogWzQwLjM4LCAtOTkuOTc2XSwKICAgICAgICB6b29tOiA1LAogICAgICAgIG1heEJvdW5kczogYm91bmRzLAogICAgICAgIGxheWVyczogW10sCiAgICAgICAgd29ybGRDb3B5SnVtcDogZmFsc2UsCiAgICAgICAgY3JzOiBMLkNSUy5FUFNHMzg1NywKICAgICAgICB6b29tQ29udHJvbDogdHJ1ZSwKICAgICAgICB9KTsKCgogICAgCiAgICB2YXIgdGlsZV9sYXllcl9lZTdiNDU0Yzc2YTM0ZDYxYmZmZDFlZWU3ZTZmYTZkZCA9IEwudGlsZUxheWVyKAogICAgICAgICdodHRwczovL3tzfS50aWxlLm9wZW5zdHJlZXRtYXAub3JnL3t6fS97eH0ve3l9LnBuZycsCiAgICAgICAgewogICAgICAgICJhdHRyaWJ1dGlvbiI6IG51bGwsCiAgICAgICAgImRldGVjdFJldGluYSI6IGZhbHNlLAogICAgICAgICJtYXhOYXRpdmVab29tIjogMTgsCiAgICAgICAgIm1heFpvb20iOiAxOCwKICAgICAgICAibWluWm9vbSI6IDAsCiAgICAgICAgIm5vV3JhcCI6IGZhbHNlLAogICAgICAgICJvcGFjaXR5IjogMSwKICAgICAgICAic3ViZG9tYWlucyI6ICJhYmMiLAogICAgICAgICJ0bXMiOiBmYWxzZQp9KS5hZGRUbyhtYXBfY2M4MTQ1NWQ5NzYxNDNmZTkzNDJhOWIwMDk2OGYwYmEpOwogICAgdmFyIHRpbGVfbGF5ZXJfNDA1ZTIyODg1YWE5NDZlN2EyYmVhMDQ4Njg5YjVkY2UgPSBMLnRpbGVMYXllcigKICAgICAgICAnaHR0cHM6Ly9lYXJ0aGVuZ2luZS5nb29nbGVhcGlzLmNvbS9tYXAvYjFkYTAzYTE2NjU5MjU4YjA3YWZjZmE5NGY4NWY4YmEve3p9L3t4fS97eX0/dG9rZW49ZmY1NGM2OWM4MTVmY2YwNzViNjBkY2JhZWYzY2RiZjYnLAogICAgICAgIHsKICAgICAgICAiYXR0cmlidXRpb24iOiAiR29vZ2xlIEVhcnRoIEVuZ2luZSIsCiAgICAgICAgImRldGVjdFJldGluYSI6IGZhbHNlLAogICAgICAgICJtYXhOYXRpdmVab29tIjogMTgsCiAgICAgICAgIm1heFpvb20iOiAxOCwKICAgICAgICAibWluWm9vbSI6IDAsCiAgICAgICAgIm5vV3JhcCI6IGZhbHNlLAogICAgICAgICJvcGFjaXR5IjogMSwKICAgICAgICAic3ViZG9tYWlucyI6ICJhYmMiLAogICAgICAgICJ0bXMiOiBmYWxzZQp9KS5hZGRUbyhtYXBfY2M4MTQ1NWQ5NzYxNDNmZTkzNDJhOWIwMDk2OGYwYmEpOwogICAgCiAgICAgICAgICAgIHZhciBsYXllcl9jb250cm9sX2Q1OGI2M2RkOWVkZTQzNjhhZDZiZGM1OWZmNmI5N2Y2ID0gewogICAgICAgICAgICAgICAgYmFzZV9sYXllcnMgOiB7ICJvcGVuc3RyZWV0bWFwIiA6IHRpbGVfbGF5ZXJfZWU3YjQ1NGM3NmEzNGQ2MWJmZmQxZWVlN2U2ZmE2ZGQsIH0sCiAgICAgICAgICAgICAgICBvdmVybGF5cyA6IHsgInBvcEltYWdlIiA6IHRpbGVfbGF5ZXJfNDA1ZTIyODg1YWE5NDZlN2EyYmVhMDQ4Njg5YjVkY2UsIH0KICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgIEwuY29udHJvbC5sYXllcnMoCiAgICAgICAgICAgICAgICBsYXllcl9jb250cm9sX2Q1OGI2M2RkOWVkZTQzNjhhZDZiZGM1OWZmNmI5N2Y2LmJhc2VfbGF5ZXJzLAogICAgICAgICAgICAgICAgbGF5ZXJfY29udHJvbF9kNThiNjNkZDllZGU0MzY4YWQ2YmRjNTlmZjZiOTdmNi5vdmVybGF5cywKICAgICAgICAgICAgICAgIHtwb3NpdGlvbjogJ3RvcHJpZ2h0JywKICAgICAgICAgICAgICAgICBjb2xsYXBzZWQ6IHRydWUsCiAgICAgICAgICAgICAgICAgYXV0b1pJbmRleDogdHJ1ZQogICAgICAgICAgICAgICAgfSkuYWRkVG8obWFwX2NjODE0NTVkOTc2MTQzZmU5MzQyYTliMDA5NjhmMGJhKTsKICAgICAgICAgICAgCiAgICAgICAgCjwvc2NyaXB0Pg==\" style=\"position:absolute;width:100%;height:100%;left:0;top:0;border:none !important;\" allowfullscreen webkitallowfullscreen mozallowfullscreen></iframe></div></div>"
            ],
            "text/plain": [
              "<folium.folium.Map at 0x7fd399363080>"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 115
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "uljo9WV8Eyy5",
        "colab_type": "text"
      },
      "source": [
        "If the features overlap, specify a reducer to indicate how to aggregate properties of overlapping features. In the previous example, since there is no overlap, an ee.Reducer.first() is sufficient. As in this example, pre-filter the data to eliminate nulls that can not be turned into an image. "
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "a6P7dqMPGHYL",
        "colab_type": "text"
      },
      "source": [
        "# 9. Grouped Reductions and Zonal Statistics\n",
        "\n",
        "You can get statistics in each zone of an `Image` or `FeatureCollection` by using `reducer.group()` to group the output of a reducer by the value of a specified input. For example, to compute the total population and number of housing units in each state, this example groups the output of a reduction of a counties `FeatureCollection` as follows:\n",
        "\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "aqr20ClRGUm_",
        "colab_type": "code",
        "outputId": "440de5f0-6e3b-4ffb-b83c-499fdc5b993c",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 935
        }
      },
      "source": [
        "# Load a collection of US counties with census data properties.\n",
        "counties = ee.FeatureCollection('ft:1S4EB6319wWW2sWQDPhDvmSBIVrD3iEmCLYB7nMM')\n",
        "\n",
        "# Compute sums of the specified properties, grouped by state name.\n",
        "sums = counties.filter(ee.Filter.And(ee.Filter.neq('Census 2000 Population', None),\n",
        "                                     ee.Filter.neq('Census 2000 Housing Units', None)))\\\n",
        "               .reduceColumns(**{\n",
        "                  'selectors': ['Census 2000 Population', 'Census 2000 Housing Units', 'StateName'],\n",
        "                  'reducer': ee.Reducer.sum().repeat(2).group(**{\n",
        "                      'groupField': 2,\n",
        "                      'groupName': 'state'})})\n",
        "\n",
        "# Print the resultant Dictionary.\n",
        "pprint(sums.getInfo())"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "{'groups': [{'state': 'Alabama', 'sum': [4447100.0, 1963711.0]},\n",
            "            {'state': 'Alaska', 'sum': [620795.0, 257020.0]},\n",
            "            {'state': 'Arizona', 'sum': [5130632.0, 2189189.0]},\n",
            "            {'state': 'Arkansas', 'sum': [2673400.0, 1173043.0]},\n",
            "            {'state': 'California', 'sum': [33871648.0, 12214549.0]},\n",
            "            {'state': 'Colorado', 'sum': [4301261.0, 1808037.0]},\n",
            "            {'state': 'Connecticut', 'sum': [3405565.0, 1385975.0]},\n",
            "            {'state': 'Delaware', 'sum': [783600.0, 343072.0]},\n",
            "            {'state': 'District of Columbia', 'sum': [572059.0, 274845.0]},\n",
            "            {'state': 'Florida', 'sum': [13729016.0, 6450669.0]},\n",
            "            {'state': 'Georgia', 'sum': [8186453.0, 3281737.0]},\n",
            "            {'state': 'Hawaii', 'sum': [1211390.0, 460370.0]},\n",
            "            {'state': 'Idaho', 'sum': [1293953.0, 527824.0]},\n",
            "            {'state': 'Illinois', 'sum': [12419293.0, 4885615.0]},\n",
            "            {'state': 'Indiana', 'sum': [6080485.0, 2532319.0]},\n",
            "            {'state': 'Iowa', 'sum': [2926324.0, 1232511.0]},\n",
            "            {'state': 'Kansas', 'sum': [2688418.0, 1131200.0]},\n",
            "            {'state': 'Kentucky', 'sum': [4041769.0, 1750927.0]},\n",
            "            {'state': 'Louisiana', 'sum': [4468976.0, 1847181.0]},\n",
            "            {'state': 'Maine', 'sum': [1274923.0, 651901.0]},\n",
            "            {'state': 'Maryland', 'sum': [5296486.0, 2145283.0]},\n",
            "            {'state': 'Massachusetts', 'sum': [6349097.0, 2621989.0]},\n",
            "            {'state': 'Michigan', 'sum': [9938444.0, 4234279.0]},\n",
            "            {'state': 'Minnesota', 'sum': [4919479.0, 2065946.0]},\n",
            "            {'state': 'Mississippi', 'sum': [2844658.0, 1161953.0]},\n",
            "            {'state': 'Missouri', 'sum': [5595211.0, 2442017.0]},\n",
            "            {'state': 'Montana', 'sum': [902195.0, 412633.0]},\n",
            "            {'state': 'Nebraska', 'sum': [1711263.0, 722668.0]},\n",
            "            {'state': 'Nevada', 'sum': [1998257.0, 827457.0]},\n",
            "            {'state': 'New Hampshire', 'sum': [1235786.0, 547024.0]},\n",
            "            {'state': 'New Jersey', 'sum': [8414350.0, 3310275.0]},\n",
            "            {'state': 'New Mexico', 'sum': [1819046.0, 780579.0]},\n",
            "            {'state': 'New York', 'sum': [18976457.0, 7679307.0]},\n",
            "            {'state': 'North Carolina', 'sum': [8049313.0, 3523944.0]},\n",
            "            {'state': 'North Dakota', 'sum': [642200.0, 289677.0]},\n",
            "            {'state': 'Ohio', 'sum': [11353140.0, 4783051.0]},\n",
            "            {'state': 'Oklahoma', 'sum': [3450654.0, 1514400.0]},\n",
            "            {'state': 'Oregon', 'sum': [3421399.0, 1452709.0]},\n",
            "            {'state': 'Pennsylvania', 'sum': [12281054.0, 5249750.0]},\n",
            "            {'state': 'Rhode Island', 'sum': [1048319.0, 439837.0]},\n",
            "            {'state': 'South Carolina', 'sum': [4012012.0, 1753670.0]},\n",
            "            {'state': 'South Dakota', 'sum': [754844.0, 323208.0]},\n",
            "            {'state': 'Tennessee', 'sum': [5689283.0, 2439443.0]},\n",
            "            {'state': 'Texas', 'sum': [20851820.0, 8157575.0]},\n",
            "            {'state': 'Utah', 'sum': [2233169.0, 768594.0]},\n",
            "            {'state': 'Vermont', 'sum': [608827.0, 294382.0]},\n",
            "            {'state': 'Virginia', 'sum': [7078515.0, 2904192.0]},\n",
            "            {'state': 'Washington', 'sum': [5894121.0, 2451075.0]},\n",
            "            {'state': 'West Virginia', 'sum': [1808344.0, 844623.0]},\n",
            "            {'state': 'Wisconsin', 'sum': [5363675.0, 2321144.0]},\n",
            "            {'state': 'Wyoming', 'sum': [493782.0, 223854.0]}]}\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "QbiBeX3aHkgO",
        "colab_type": "text"
      },
      "source": [
        "The `groupField` argument is the index of the input in the selectors array that contains the codes by which to group, the `groupName` argument specifies the name of the property to store the value of the grouping variable. Since the reducer is not automatically repeated for each input, the `repeat(2)` call is needed.\n",
        "\n",
        "To group output of `image.reduceRegions()` you can specify a grouping band that defines groups by integer pixel values. This type of computation is sometimes called \"zonal statistics\" where the zones are specified as the grouping band and the statistic is determined by the reducer. In the following example, change in nightlights in the United States is grouped by land cover category:"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "yskKEEfSHyHj",
        "colab_type": "code",
        "outputId": "b667cc3f-721f-4fa4-8dee-6a43d54ec12e",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 323
        }
      },
      "source": [
        "# Load a region representing the United States\n",
        "region = ee.Feature(ee.FeatureCollection('ft:1tdSwUL7MVpOauSgRzqVTOwdfy17KDbw-1d9omPw')\\\n",
        "                      .filter(ee.Filter.eq('Country', 'United States'))\\\n",
        "                      .first())\n",
        "\n",
        "# Load MODIS land cover categories in 2001.\n",
        "landcover = ee.Image('MODIS/051/MCD12Q1/2001_01_01')\\\n",
        "              .select('Land_Cover_Type_1') # Select the IGBP classification band.\n",
        "\n",
        "# Load nightlights image inputs.\n",
        "nl2001 = ee.Image('NOAA/DMSP-OLS/NIGHTTIME_LIGHTS/F152001')\\\n",
        "           .select('stable_lights')\n",
        "\n",
        "nl2012 = ee.Image('NOAA/DMSP-OLS/NIGHTTIME_LIGHTS/F182012')\\\n",
        "           .select('stable_lights')\n",
        "\n",
        "# Compute the nightlights decadal difference, add land cover codes.\n",
        "nlDiff = nl2012.subtract(nl2001).addBands(landcover)\n",
        "\n",
        "# Grouped a mean reducer: change of nightlights by land cover category.\n",
        "means = nlDiff.reduceRegion(**{\n",
        "  'reducer': ee.Reducer.mean().group(**{\n",
        "    'groupField': 1,\n",
        "    'groupName': 'code',\n",
        "  }),\n",
        "  'geometry': region.geometry(),\n",
        "  'scale': 1000,\n",
        "  'maxPixels': 1e8\n",
        "});\n",
        "\n",
        "# Print the resultant Dictionary.\n",
        "pprint(means.getInfo())"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "{'groups': [{'code': 0, 'mean': -0.11172072503842889},\n",
            "            {'code': 1, 'mean': -0.10531694840105481},\n",
            "            {'code': 2, 'mean': 0.5319690050938765},\n",
            "            {'code': 3, 'mean': -0.2348240630931086},\n",
            "            {'code': 4, 'mean': -0.23063576587635104},\n",
            "            {'code': 5, 'mean': 0.014154122164175172},\n",
            "            {'code': 6, 'mean': 0.4316131220363849},\n",
            "            {'code': 7, 'mean': 0.1385422162199612},\n",
            "            {'code': 8, 'mean': 0.40154603020642976},\n",
            "            {'code': 9, 'mean': 0.19139864991972394},\n",
            "            {'code': 10, 'mean': 0.1837396574848538},\n",
            "            {'code': 11, 'mean': 0.20074970826357522},\n",
            "            {'code': 12, 'mean': -0.2169800337243732},\n",
            "            {'code': 13, 'mean': 0.28636567428499526},\n",
            "            {'code': 14, 'mean': -0.06603301038183143},\n",
            "            {'code': 15, 'mean': 0.025706054801271267},\n",
            "            {'code': 16, 'mean': 0.1768030496705951}]}\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "1oOg4NNLIU7Q",
        "colab_type": "text"
      },
      "source": [
        "Note that in this example, the `groupField` is the index of the band containing the zones by which to group the output. The first band is index 0, the second is index 1, etc."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "tLRnPAmoNKW-",
        "colab_type": "text"
      },
      "source": [
        "# 10. Weighted Reductions\n",
        "\n",
        "By default, reducers applied to imagery weight the inputs according to the mask value. This is relevant in the context of fractional pixels created through operations such as `clip()`. Adjust this behavior by calling `unweighted()` on the reducer. Using an unweighted reducer forces all pixels in the region to have the same weight. The following example illustrates how pixel weighting can affect the reducer output:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "ta9risk8NRSm",
        "colab_type": "code",
        "outputId": "271205b6-eac5-4322-d793-a51636abf0ba",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 53
        }
      },
      "source": [
        "# Load a Landsat 8 input image.\n",
        "image = ee.Image('LANDSAT/LC08/C01/T1/LC08_044034_20140318')\n",
        "\n",
        "# Creat an arbitrary region.\n",
        "geometry = ee.Geometry.Rectangle(-122.496, 37.532, -121.554, 37.538)\n",
        "\n",
        "# Make an NDWI image.  It will have one band named 'nd'.\n",
        "ndwi = image.normalizedDifference(['B3', 'B5']);\n",
        "\n",
        "# Compute the weighted mean of the NDWI image clipped to the region.\n",
        "weighted = ndwi.clip(geometry)\\\n",
        "               .reduceRegion(**{'reducer': ee.Reducer.sum(),\n",
        "                              'geometry': geometry,\n",
        "                              'scale': 30})\\\n",
        "               .get('nd')\n",
        "\n",
        "# Compute the UN-weighted mean of the NDWI image clipped to the region.\n",
        "unweighted = ndwi.clip(geometry)\\\n",
        "                 .reduceRegion(**{'reducer': ee.Reducer.sum().unweighted(),\n",
        "                                'geometry': geometry,\n",
        "                                'scale': 30}).get('nd')\n",
        "\n",
        "# Observe the difference between weighted and unweighted reductions.\n",
        "print('weighted:', weighted.getInfo())\n",
        "print('unweighted', unweighted.getInfo())"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "weighted: -9081.917068950213\n",
            "unweighted -9086.503929115412\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "pc1OnlaXNv-K",
        "colab_type": "text"
      },
      "source": [
        "The difference in results is due to pixels at the edge of the region receiving a weight of one as a result of calling `unweighted()` on the reducer.\n",
        "\n",
        "In order to obtain an explicitly weighted output, it is preferable to set the weights explicitly with `splitWeights()` called on the reducer. A reducer modified by `splitWeights()` takes two inputs, where the second input is the weight. The following example illustrates `splitWeights()` by computing the weighted mean Normalized Difference Vegetation Index (NDVI) in a region, with the weights given by cloud score (the cloudier, the lower the weight):"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "VyzRPM8rOfJx",
        "colab_type": "code",
        "outputId": "716497cb-4fdf-491e-add6-c2d82cb2b262",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 53
        }
      },
      "source": [
        "# Load an input Landsat 8 image.\n",
        "image = ee.Image('LANDSAT/LC08/C01/T1_TOA/LC08_186059_20130419')\n",
        "\n",
        "# Compute cloud score and reverse it such that the highest\n",
        "# weight (100) is for the least cloudy pixels.\n",
        "cloudWeight = ee.Image(100).subtract(\n",
        "  ee.Algorithms.Landsat.simpleCloudScore(image).select(['cloud']))\n",
        "\n",
        "# Compute NDVI and add the cloud weight band.\n",
        "ndvi = image.normalizedDifference(['B5', 'B4']).addBands(cloudWeight)\n",
        "\n",
        "# Define an arbitrary region in a cloudy area.\n",
        "region = ee.Geometry.Rectangle(9.9069, 0.5981, 10.5, 0.9757)\n",
        "\n",
        "# Use a mean reducer.\n",
        "reducer = ee.Reducer.mean()\n",
        "\n",
        "# Compute the unweighted mean.\n",
        "unweighted = ndvi.select(['nd']).reduceRegion(reducer, region, 30)\n",
        "\n",
        "# compute mean weighted by cloudiness.\n",
        "weighted = ndvi.reduceRegion(reducer.splitWeights(), region, 30);\n",
        "\n",
        "# Observe the difference as a result of weighting by cloudiness.\n",
        "print('unweighted:', unweighted.getInfo())\n",
        "print('weighted:', weighted.getInfo())"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "unweighted: {'nd': 0.49304970804714043}\n",
            "weighted: {'mean': 0.587125215732146}\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "U4xKLV0pOvZ7",
        "colab_type": "text"
      },
      "source": [
        "Observe that cloudWeight needs to be added as a band prior to calling reduceRegion(). The result indicates that the estimated mean NDVI is higher as a result of decreasing the weight of cloudy pixels.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "VEL353Z3PEvM",
        "colab_type": "text"
      },
      "source": [
        "# 11. Linear Regression\n",
        "\n",
        "Earth Engine contains a variety of methods for performing linear regression using reducers. The simplest linear regression reducer is `ee.Reducer.linearFit()` which computes the least squares estimate of a linear function of one variable with a constant term. The data should be set up as a two-band input image, where the first band is the independent variable and the second band is the dependent variable. The following example shows estimation of the linear trend of future precipitation (after 2006 in the [NEX data](https://developers.google.com/earth-engine/datasets/catalog/NASA_NEX-DCP30)) projected by climate models. The dependent variable is projected precipitation and the independent variable is time, added prior to calling `linearFit()`:"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "7_IAMUr_Ps3V",
        "colab_type": "code",
        "outputId": "ab569fb3-47c4-4ef1-f5c6-16eaa5813b03",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 559
        }
      },
      "source": [
        "# This function adds a time band to the image.\n",
        "def createTimeBand(image):\n",
        "  # Scale milliseconds by a large constant to avoid very small slopes\n",
        "  # in the linear regression output.\n",
        "  return image.addBands(image.metadata('system:time_start').divide(1e18))\n",
        "\n",
        "\n",
        "# Load the input image collection: projected climate data.\n",
        "collection = ee.ImageCollection('NASA/NEX-DCP30_ENSEMBLE_STATS')\\\n",
        "               .filter(ee.Filter.eq('scenario', 'rcp85'))\\\n",
        "               .filterDate(ee.Date('2006-01-01'), ee.Date('2050-01-01'))\\\n",
        "               .map(createTimeBand) #Map the time band function over the collection.\n",
        "\n",
        "# Reduce the collection with the linear fit reducer.\n",
        "# Independent variable are followed by dependent variables.\n",
        "linearFit = collection.select(['system:time_start', 'pr_mean'])\\\n",
        "                      .reduce(ee.Reducer.linearFit())\n",
        "\n",
        "# Display the results.\n",
        "center = [40.38,-100.11]\n",
        "lineargm = linearFit.getMapId({'min': 0, 'max': [-0.9, 8e-5, 1], 'bands': ['scale', 'offset', 'scale']})\n",
        "Mapdisplay(center,{'fit':lineargm},zoom_start=5)"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/html": [
              "<div style=\"width:100%;\"><div style=\"position:relative;width:100%;height:0;padding-bottom:60%;\"><iframe src=\"data:text/html;charset=utf-8;base64,PCFET0NUWVBFIGh0bWw+CjxoZWFkPiAgICAKICAgIDxtZXRhIGh0dHAtZXF1aXY9ImNvbnRlbnQtdHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PVVURi04IiAvPgogICAgPHNjcmlwdD5MX1BSRUZFUl9DQU5WQVM9ZmFsc2U7IExfTk9fVE9VQ0g9ZmFsc2U7IExfRElTQUJMRV8zRD1mYWxzZTs8L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS40LjAvZGlzdC9sZWFmbGV0LmpzIj48L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2NvZGUuanF1ZXJ5LmNvbS9qcXVlcnktMS4xMi40Lm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvanMvYm9vdHN0cmFwLm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9jZG5qcy5jbG91ZGZsYXJlLmNvbS9hamF4L2xpYnMvTGVhZmxldC5hd2Vzb21lLW1hcmtlcnMvMi4wLjIvbGVhZmxldC5hd2Vzb21lLW1hcmtlcnMuanMiPjwvc2NyaXB0PgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS40LjAvZGlzdC9sZWFmbGV0LmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9jc3MvYm9vdHN0cmFwLm1pbi5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvY3NzL2Jvb3RzdHJhcC10aGVtZS5taW4uY3NzIi8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vbWF4Y2RuLmJvb3RzdHJhcGNkbi5jb20vZm9udC1hd2Vzb21lLzQuNi4zL2Nzcy9mb250LWF3ZXNvbWUubWluLmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2NkbmpzLmNsb3VkZmxhcmUuY29tL2FqYXgvbGlicy9MZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy8yLjAuMi9sZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9yYXdjZG4uZ2l0aGFjay5jb20vcHl0aG9uLXZpc3VhbGl6YXRpb24vZm9saXVtL21hc3Rlci9mb2xpdW0vdGVtcGxhdGVzL2xlYWZsZXQuYXdlc29tZS5yb3RhdGUuY3NzIi8+CiAgICA8c3R5bGU+aHRtbCwgYm9keSB7d2lkdGg6IDEwMCU7aGVpZ2h0OiAxMDAlO21hcmdpbjogMDtwYWRkaW5nOiAwO308L3N0eWxlPgogICAgPHN0eWxlPiNtYXAge3Bvc2l0aW9uOmFic29sdXRlO3RvcDowO2JvdHRvbTowO3JpZ2h0OjA7bGVmdDowO308L3N0eWxlPgogICAgCiAgICA8bWV0YSBuYW1lPSJ2aWV3cG9ydCIgY29udGVudD0id2lkdGg9ZGV2aWNlLXdpZHRoLAogICAgICAgIGluaXRpYWwtc2NhbGU9MS4wLCBtYXhpbXVtLXNjYWxlPTEuMCwgdXNlci1zY2FsYWJsZT1ubyIgLz4KICAgIDxzdHlsZT4jbWFwX2M0N2RlNjcyOWVlOTQ0NzQ5YWQzM2NjMTMwNDFkNjc1IHsKICAgICAgICBwb3NpdGlvbjogcmVsYXRpdmU7CiAgICAgICAgd2lkdGg6IDEwMC4wJTsKICAgICAgICBoZWlnaHQ6IDEwMC4wJTsKICAgICAgICBsZWZ0OiAwLjAlOwogICAgICAgIHRvcDogMC4wJTsKICAgICAgICB9CiAgICA8L3N0eWxlPgo8L2hlYWQ+Cjxib2R5PiAgICAKICAgIAogICAgPGRpdiBjbGFzcz0iZm9saXVtLW1hcCIgaWQ9Im1hcF9jNDdkZTY3MjllZTk0NDc0OWFkMzNjYzEzMDQxZDY3NSIgPjwvZGl2Pgo8L2JvZHk+CjxzY3JpcHQ+ICAgIAogICAgCiAgICAKICAgICAgICB2YXIgYm91bmRzID0gbnVsbDsKICAgIAoKICAgIHZhciBtYXBfYzQ3ZGU2NzI5ZWU5NDQ3NDlhZDMzY2MxMzA0MWQ2NzUgPSBMLm1hcCgKICAgICAgICAnbWFwX2M0N2RlNjcyOWVlOTQ0NzQ5YWQzM2NjMTMwNDFkNjc1JywgewogICAgICAgIGNlbnRlcjogWzQwLjM4LCAtMTAwLjExXSwKICAgICAgICB6b29tOiA1LAogICAgICAgIG1heEJvdW5kczogYm91bmRzLAogICAgICAgIGxheWVyczogW10sCiAgICAgICAgd29ybGRDb3B5SnVtcDogZmFsc2UsCiAgICAgICAgY3JzOiBMLkNSUy5FUFNHMzg1NywKICAgICAgICB6b29tQ29udHJvbDogdHJ1ZSwKICAgICAgICB9KTsKCgogICAgCiAgICB2YXIgdGlsZV9sYXllcl8zNWMwODJiNDkxZmQ0ZjM3OGY2Y2I2MjdmMGU2Zjg3MyA9IEwudGlsZUxheWVyKAogICAgICAgICdodHRwczovL3tzfS50aWxlLm9wZW5zdHJlZXRtYXAub3JnL3t6fS97eH0ve3l9LnBuZycsCiAgICAgICAgewogICAgICAgICJhdHRyaWJ1dGlvbiI6IG51bGwsCiAgICAgICAgImRldGVjdFJldGluYSI6IGZhbHNlLAogICAgICAgICJtYXhOYXRpdmVab29tIjogMTgsCiAgICAgICAgIm1heFpvb20iOiAxOCwKICAgICAgICAibWluWm9vbSI6IDAsCiAgICAgICAgIm5vV3JhcCI6IGZhbHNlLAogICAgICAgICJvcGFjaXR5IjogMSwKICAgICAgICAic3ViZG9tYWlucyI6ICJhYmMiLAogICAgICAgICJ0bXMiOiBmYWxzZQp9KS5hZGRUbyhtYXBfYzQ3ZGU2NzI5ZWU5NDQ3NDlhZDMzY2MxMzA0MWQ2NzUpOwogICAgdmFyIHRpbGVfbGF5ZXJfN2Q5NzU4NzI0ZGYxNDg2ZWEzMzczM2RkMjExNTI5OTUgPSBMLnRpbGVMYXllcigKICAgICAgICAnaHR0cHM6Ly9lYXJ0aGVuZ2luZS5nb29nbGVhcGlzLmNvbS9tYXAvMDBiN2Q0ZjAxOGQyZjNjOWY5OGYwMzVkOTM1OGNhNDkve3p9L3t4fS97eX0/dG9rZW49OWZlNzgyNmExYjczZDcyZWNiNzA3YjY5ZjE3ZmIyOWYnLAogICAgICAgIHsKICAgICAgICAiYXR0cmlidXRpb24iOiAiR29vZ2xlIEVhcnRoIEVuZ2luZSIsCiAgICAgICAgImRldGVjdFJldGluYSI6IGZhbHNlLAogICAgICAgICJtYXhOYXRpdmVab29tIjogMTgsCiAgICAgICAgIm1heFpvb20iOiAxOCwKICAgICAgICAibWluWm9vbSI6IDAsCiAgICAgICAgIm5vV3JhcCI6IGZhbHNlLAogICAgICAgICJvcGFjaXR5IjogMSwKICAgICAgICAic3ViZG9tYWlucyI6ICJhYmMiLAogICAgICAgICJ0bXMiOiBmYWxzZQp9KS5hZGRUbyhtYXBfYzQ3ZGU2NzI5ZWU5NDQ3NDlhZDMzY2MxMzA0MWQ2NzUpOwogICAgCiAgICAgICAgICAgIHZhciBsYXllcl9jb250cm9sXzI0MzQ2YzEyMWEwZTRjNTZhZTIxNmZiMWQyMzAyOTA3ID0gewogICAgICAgICAgICAgICAgYmFzZV9sYXllcnMgOiB7ICJvcGVuc3RyZWV0bWFwIiA6IHRpbGVfbGF5ZXJfMzVjMDgyYjQ5MWZkNGYzNzhmNmNiNjI3ZjBlNmY4NzMsIH0sCiAgICAgICAgICAgICAgICBvdmVybGF5cyA6IHsgImZpdCIgOiB0aWxlX2xheWVyXzdkOTc1ODcyNGRmMTQ4NmVhMzM3MzNkZDIxMTUyOTk1LCB9CiAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICBMLmNvbnRyb2wubGF5ZXJzKAogICAgICAgICAgICAgICAgbGF5ZXJfY29udHJvbF8yNDM0NmMxMjFhMGU0YzU2YWUyMTZmYjFkMjMwMjkwNy5iYXNlX2xheWVycywKICAgICAgICAgICAgICAgIGxheWVyX2NvbnRyb2xfMjQzNDZjMTIxYTBlNGM1NmFlMjE2ZmIxZDIzMDI5MDcub3ZlcmxheXMsCiAgICAgICAgICAgICAgICB7cG9zaXRpb246ICd0b3ByaWdodCcsCiAgICAgICAgICAgICAgICAgY29sbGFwc2VkOiB0cnVlLAogICAgICAgICAgICAgICAgIGF1dG9aSW5kZXg6IHRydWUKICAgICAgICAgICAgICAgIH0pLmFkZFRvKG1hcF9jNDdkZTY3MjllZTk0NDc0OWFkMzNjYzEzMDQxZDY3NSk7CiAgICAgICAgICAgIAogICAgICAgIAo8L3NjcmlwdD4=\" style=\"position:absolute;width:100%;height:100%;left:0;top:0;border:none !important;\" allowfullscreen webkitallowfullscreen mozallowfullscreen></iframe></div></div>"
            ],
            "text/plain": [
              "<folium.folium.Map at 0x7fd3993546a0>"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 134
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "az_2nrATRE9w",
        "colab_type": "text"
      },
      "source": [
        "Observe that the output contains two bands, the `‘offset’` (intercept) and the `‘scale’` ('scale' in this context refers to the slope of the line and is not to be confused with the scale parameter input to many reducers, which is the spatial scale). The result, with areas of increasing trend in blue, decreasing trend in red and no trend in green should look something like the Map above.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "bE1TUvBjRhch",
        "colab_type": "text"
      },
      "source": [
        "For a more flexible approach to linear modelling, use one of the linear regression reducers which allow for a variable number of independent and dependent variables. Specifically, `ee.Reducer.linearRegression()` implements ordinary least squares regression (OLS). Alternatively, `robustLinearRegression()` uses a cost function based on regression residuals to iteratively de-weight outliers in the data ([O’Leary 1990](https://epubs.siam.org/doi/abs/10.1137/0611032)).\n",
        "\n",
        "For example, suppose there are two dependent variables: precipitation and maximum temperature, and two independent variables: a constant and time. The collection is identical to the previous example, but the constant band must be manually added prior to the reduction. The first two bands of the input are the ‘X’ (independent) variables and the next two bands are the ‘Y’ (dependent) variables. In this example, first get the regression coefficients, then flatten the array image to extract the bands of interest:"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "HlxHMDIKRv3j",
        "colab_type": "code",
        "outputId": "4ae6fa5a-42a6-435d-905e-4f6cccd02ee9",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 559
        }
      },
      "source": [
        "# This function adds a time band to the image.\n",
        "def createTimeBand(image):\n",
        "  # Scale milliseconds by a large constant.\n",
        "  return image.addBands(image.metadata('system:time_start').divide(1e18))\n",
        "\n",
        "\n",
        "# This function adds a constant band to the image.\n",
        "def createConstantBand(image):\n",
        "  return ee.Image(1).addBands(image)\n",
        "\n",
        "# Load the input image collection: projected climate data.\n",
        "# 1. Map the functions over the collection, to get constant and time bands.\n",
        "# 2. Select the predictors and the responses.\n",
        "collection = ee.ImageCollection('NASA/NEX-DCP30_ENSEMBLE_STATS')\\\n",
        "               .filterDate(ee.Date('2006-01-01'), ee.Date('2099-01-01'))\\\n",
        "               .filter(ee.Filter.eq('scenario', 'rcp85'))\\\n",
        "               .map(createTimeBand)\\\n",
        "               .map(createConstantBand)\\\n",
        "               .select(['constant', 'system:time_start', 'pr_mean', 'tasmax_mean'])\n",
        "\n",
        "# Compute ordinary least squares regression coefficients.\n",
        "linearRegression = collection.reduce(\n",
        "  ee.Reducer.linearRegression(**{\n",
        "    'numX': 2,\n",
        "    'numY': 2\n",
        "}))\n",
        "\n",
        "# Compute robust linear regression coefficients.\n",
        "robustLinearRegression = collection.reduce(\n",
        "  ee.Reducer.robustLinearRegression(**{\n",
        "    'numX': 2,\n",
        "    'numY': 2\n",
        "}))\n",
        "\n",
        "# The results are array images that must be flattened for display.\n",
        "# These lists label the information along each axis of the arrays.\n",
        "bandNames = [['constant', 'time'], # 0-axis variation.\n",
        "             ['precip', 'temp']] # 1-axis variation.\n",
        "\n",
        "# Flatten the array images to get multi-band images according to the labels.\n",
        "lrImage = linearRegression.select(['coefficients']).arrayFlatten(bandNames)\n",
        "rlrImage = robustLinearRegression.select(['coefficients']).arrayFlatten(bandNames)\n",
        "\n",
        "# Display the OLS results.\n",
        "center = [40.38,-100.11]\n",
        "lrImage_tk = lrImage.getMapId({'min': 0, \n",
        "                           'max': [-0.9, 8e-5, 1],\n",
        "                           'bands': ['time_precip', 'constant_precip', 'time_precip']})\n",
        "\n",
        "Mapdisplay(center,{'OLS':lrImage_tk},zoom_start=5)"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/html": [
              "<div style=\"width:100%;\"><div style=\"position:relative;width:100%;height:0;padding-bottom:60%;\"><iframe src=\"data:text/html;charset=utf-8;base64,PCFET0NUWVBFIGh0bWw+CjxoZWFkPiAgICAKICAgIDxtZXRhIGh0dHAtZXF1aXY9ImNvbnRlbnQtdHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PVVURi04IiAvPgogICAgPHNjcmlwdD5MX1BSRUZFUl9DQU5WQVM9ZmFsc2U7IExfTk9fVE9VQ0g9ZmFsc2U7IExfRElTQUJMRV8zRD1mYWxzZTs8L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS40LjAvZGlzdC9sZWFmbGV0LmpzIj48L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2NvZGUuanF1ZXJ5LmNvbS9qcXVlcnktMS4xMi40Lm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvanMvYm9vdHN0cmFwLm1pbi5qcyI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9jZG5qcy5jbG91ZGZsYXJlLmNvbS9hamF4L2xpYnMvTGVhZmxldC5hd2Vzb21lLW1hcmtlcnMvMi4wLjIvbGVhZmxldC5hd2Vzb21lLW1hcmtlcnMuanMiPjwvc2NyaXB0PgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2xlYWZsZXRAMS40LjAvZGlzdC9sZWFmbGV0LmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9jc3MvYm9vdHN0cmFwLm1pbi5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9ib290c3RyYXAvMy4yLjAvY3NzL2Jvb3RzdHJhcC10aGVtZS5taW4uY3NzIi8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vbWF4Y2RuLmJvb3RzdHJhcGNkbi5jb20vZm9udC1hd2Vzb21lLzQuNi4zL2Nzcy9mb250LWF3ZXNvbWUubWluLmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL2NkbmpzLmNsb3VkZmxhcmUuY29tL2FqYXgvbGlicy9MZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy8yLjAuMi9sZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9yYXdjZG4uZ2l0aGFjay5jb20vcHl0aG9uLXZpc3VhbGl6YXRpb24vZm9saXVtL21hc3Rlci9mb2xpdW0vdGVtcGxhdGVzL2xlYWZsZXQuYXdlc29tZS5yb3RhdGUuY3NzIi8+CiAgICA8c3R5bGU+aHRtbCwgYm9keSB7d2lkdGg6IDEwMCU7aGVpZ2h0OiAxMDAlO21hcmdpbjogMDtwYWRkaW5nOiAwO308L3N0eWxlPgogICAgPHN0eWxlPiNtYXAge3Bvc2l0aW9uOmFic29sdXRlO3RvcDowO2JvdHRvbTowO3JpZ2h0OjA7bGVmdDowO308L3N0eWxlPgogICAgCiAgICA8bWV0YSBuYW1lPSJ2aWV3cG9ydCIgY29udGVudD0id2lkdGg9ZGV2aWNlLXdpZHRoLAogICAgICAgIGluaXRpYWwtc2NhbGU9MS4wLCBtYXhpbXVtLXNjYWxlPTEuMCwgdXNlci1zY2FsYWJsZT1ubyIgLz4KICAgIDxzdHlsZT4jbWFwXzgxOGYwOTg1Y2ZjNDQyMDI5Y2M5ZTc4MTI4ZGM1YjY1IHsKICAgICAgICBwb3NpdGlvbjogcmVsYXRpdmU7CiAgICAgICAgd2lkdGg6IDEwMC4wJTsKICAgICAgICBoZWlnaHQ6IDEwMC4wJTsKICAgICAgICBsZWZ0OiAwLjAlOwogICAgICAgIHRvcDogMC4wJTsKICAgICAgICB9CiAgICA8L3N0eWxlPgo8L2hlYWQ+Cjxib2R5PiAgICAKICAgIAogICAgPGRpdiBjbGFzcz0iZm9saXVtLW1hcCIgaWQ9Im1hcF84MThmMDk4NWNmYzQ0MjAyOWNjOWU3ODEyOGRjNWI2NSIgPjwvZGl2Pgo8L2JvZHk+CjxzY3JpcHQ+ICAgIAogICAgCiAgICAKICAgICAgICB2YXIgYm91bmRzID0gbnVsbDsKICAgIAoKICAgIHZhciBtYXBfODE4ZjA5ODVjZmM0NDIwMjljYzllNzgxMjhkYzViNjUgPSBMLm1hcCgKICAgICAgICAnbWFwXzgxOGYwOTg1Y2ZjNDQyMDI5Y2M5ZTc4MTI4ZGM1YjY1JywgewogICAgICAgIGNlbnRlcjogWzQwLjM4LCAtMTAwLjExXSwKICAgICAgICB6b29tOiA1LAogICAgICAgIG1heEJvdW5kczogYm91bmRzLAogICAgICAgIGxheWVyczogW10sCiAgICAgICAgd29ybGRDb3B5SnVtcDogZmFsc2UsCiAgICAgICAgY3JzOiBMLkNSUy5FUFNHMzg1NywKICAgICAgICB6b29tQ29udHJvbDogdHJ1ZSwKICAgICAgICB9KTsKCgogICAgCiAgICB2YXIgdGlsZV9sYXllcl9lNWFjN2MzNDFkN2M0NDA3OWJkMmNjNjdhOTE5Y2M5OSA9IEwudGlsZUxheWVyKAogICAgICAgICdodHRwczovL3tzfS50aWxlLm9wZW5zdHJlZXRtYXAub3JnL3t6fS97eH0ve3l9LnBuZycsCiAgICAgICAgewogICAgICAgICJhdHRyaWJ1dGlvbiI6IG51bGwsCiAgICAgICAgImRldGVjdFJldGluYSI6IGZhbHNlLAogICAgICAgICJtYXhOYXRpdmVab29tIjogMTgsCiAgICAgICAgIm1heFpvb20iOiAxOCwKICAgICAgICAibWluWm9vbSI6IDAsCiAgICAgICAgIm5vV3JhcCI6IGZhbHNlLAogICAgICAgICJvcGFjaXR5IjogMSwKICAgICAgICAic3ViZG9tYWlucyI6ICJhYmMiLAogICAgICAgICJ0bXMiOiBmYWxzZQp9KS5hZGRUbyhtYXBfODE4ZjA5ODVjZmM0NDIwMjljYzllNzgxMjhkYzViNjUpOwogICAgdmFyIHRpbGVfbGF5ZXJfNzNhOWVkOWYwNTk1NGZkNzgyOWI2MTBlN2YyOGNlZjIgPSBMLnRpbGVMYXllcigKICAgICAgICAnaHR0cHM6Ly9lYXJ0aGVuZ2luZS5nb29nbGVhcGlzLmNvbS9tYXAvODRmNzhlYWNiNDg1MDY3Nzg5Y2FjMDk4ZmFmYzg0YTIve3p9L3t4fS97eX0/dG9rZW49M2NhOGM5OWYyNDAzYTg1MmYzNTllMmEwNTQ3ZDhkMmInLAogICAgICAgIHsKICAgICAgICAiYXR0cmlidXRpb24iOiAiR29vZ2xlIEVhcnRoIEVuZ2luZSIsCiAgICAgICAgImRldGVjdFJldGluYSI6IGZhbHNlLAogICAgICAgICJtYXhOYXRpdmVab29tIjogMTgsCiAgICAgICAgIm1heFpvb20iOiAxOCwKICAgICAgICAibWluWm9vbSI6IDAsCiAgICAgICAgIm5vV3JhcCI6IGZhbHNlLAogICAgICAgICJvcGFjaXR5IjogMSwKICAgICAgICAic3ViZG9tYWlucyI6ICJhYmMiLAogICAgICAgICJ0bXMiOiBmYWxzZQp9KS5hZGRUbyhtYXBfODE4ZjA5ODVjZmM0NDIwMjljYzllNzgxMjhkYzViNjUpOwogICAgCiAgICAgICAgICAgIHZhciBsYXllcl9jb250cm9sX2NhZGNmNmQyODcyMDQ0YjM4NTBkNTM0ZjY1Yjg4MDJiID0gewogICAgICAgICAgICAgICAgYmFzZV9sYXllcnMgOiB7ICJvcGVuc3RyZWV0bWFwIiA6IHRpbGVfbGF5ZXJfZTVhYzdjMzQxZDdjNDQwNzliZDJjYzY3YTkxOWNjOTksIH0sCiAgICAgICAgICAgICAgICBvdmVybGF5cyA6IHsgIk9MUyIgOiB0aWxlX2xheWVyXzczYTllZDlmMDU5NTRmZDc4MjliNjEwZTdmMjhjZWYyLCB9CiAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICBMLmNvbnRyb2wubGF5ZXJzKAogICAgICAgICAgICAgICAgbGF5ZXJfY29udHJvbF9jYWRjZjZkMjg3MjA0NGIzODUwZDUzNGY2NWI4ODAyYi5iYXNlX2xheWVycywKICAgICAgICAgICAgICAgIGxheWVyX2NvbnRyb2xfY2FkY2Y2ZDI4NzIwNDRiMzg1MGQ1MzRmNjViODgwMmIub3ZlcmxheXMsCiAgICAgICAgICAgICAgICB7cG9zaXRpb246ICd0b3ByaWdodCcsCiAgICAgICAgICAgICAgICAgY29sbGFwc2VkOiB0cnVlLAogICAgICAgICAgICAgICAgIGF1dG9aSW5kZXg6IHRydWUKICAgICAgICAgICAgICAgIH0pLmFkZFRvKG1hcF84MThmMDk4NWNmYzQ0MjAyOWNjOWU3ODEyOGRjNWI2NSk7CiAgICAgICAgICAgIAogICAgICAgIAo8L3NjcmlwdD4=\" style=\"position:absolute;width:100%;height:100%;left:0;top:0;border:none !important;\" allowfullscreen webkitallowfullscreen mozallowfullscreen></iframe></div></div>"
            ],
            "text/plain": [
              "<folium.folium.Map at 0x7fd399307a58>"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 141
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "9loXBt_6Uj2d",
        "colab_type": "code",
        "outputId": "a3a149e3-b890-439f-e5bf-2a158a5df564",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 197
        }
      },
      "source": [
        "# Compare the results at a specific point:\n",
        "print('OLS estimates:')\n",
        "pprint(lrImage.reduceRegion(**{\n",
        "  'reducer': ee.Reducer.first(),\n",
        "  'geometry': ee.Geometry.Point([-96.0, 41.0]),\n",
        "  'scale': 1000\n",
        "}).getInfo())\n",
        "\n",
        "print('Robust estimates:')\n",
        "pprint(rlrImage.reduceRegion(**{\n",
        "  'reducer': ee.Reducer.first(),\n",
        "  'geometry': ee.Geometry.Point([-96.0, 41.0]),\n",
        "  'scale': 1000\n",
        "}).getInfo())"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "OLS estimates:\n",
            "{'constant_precip': 2.4574870622018352e-05,\n",
            " 'constant_temp': 288.0090637207031,\n",
            " 'time_precip': 0.620400607585907,\n",
            " 'time_temp': 2055808.75}\n",
            "Robust estimates:\n",
            "{'constant_precip': 2.742403739830479e-05,\n",
            " 'constant_temp': 288.0704650878906,\n",
            " 'time_precip': 2.982717752456665,\n",
            " 'time_temp': 2032093.375}\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "U1gxORtJVIS8",
        "colab_type": "text"
      },
      "source": [
        "Inspect the results to discover that `linearRegression()` output is equivalent to the coefficients estimated by the `linearFit()` reducer, though the `linearRegression()` output also has coefficients for the other dependent variable, `tasmax_mean`. Robust linear regression coefficients are different from the OLS estimates. The example compares the coefficients from the different regression methods at a specific point."
      ]
    }
  ]
}